From ee26261fb03f0a1db2aed06740e3397e8acebc0b Mon Sep 17 00:00:00 2001 From: xuxingliang Date: Fri, 8 Nov 2024 12:28:26 +0800 Subject: [PATCH 001/235] gdb/lists: add element option to foreach list VELAPLATFO-45911 So we can focus on single element of struct, same as array. Fix typo in foreach array args.element Change-Id: Ib1acfa7ffc2dcca41234aadcd9ec355dd16b32db Signed-off-by: xuxingliang --- tools/gdb/nuttxgdb/lists.py | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/tools/gdb/nuttxgdb/lists.py b/tools/gdb/nuttxgdb/lists.py index ec4defcdbcd..4cec7e81cae 100644 --- a/tools/gdb/nuttxgdb/lists.py +++ b/tools/gdb/nuttxgdb/lists.py @@ -347,6 +347,13 @@ class ForeachListEntry(gdb.Command): parser.add_argument( "-m", "--member", type=str, default=None, help="Member name in container" ) + parser.add_argument( + "-e", + "--element", + type=str, + help="Only dump this element in array member struct.", + default=None, + ) try: args = parser.parse_args(argv) except SystemExit: @@ -363,6 +370,7 @@ class ForeachListEntry(gdb.Command): else node ) entry = entry.dereference() + entry = entry[args.element] if args.element else entry gdb.write( f"{i} *({entry.type} *){hex(entry.address)} {entry.format_string(styling=True)}\n" ) @@ -407,5 +415,5 @@ class ForeachArray(gdb.Command): node = pointer len = args.length if args.length else utils.nitems(pointer) for i in range(len): - entry = node[i][args.element] if arg.element else node[i] + entry = node[i][args.element] if args.element else node[i] gdb.write(f"{i}: {entry.format_string(styling=True)}\n") -- Gitee From cc092227ca58370a993177db906c26deda980a4e Mon Sep 17 00:00:00 2001 From: xuxingliang Date: Fri, 8 Nov 2024 13:28:01 +0800 Subject: [PATCH 002/235] gdb/utils: enhance utils.Value VELAPLATFO-45211 Added __format__ method to support format spec like {:>10} that gdb.Value doesn't support. For such case, gdb.Value is converted to python value firstly and then format natively. Override all methods/attributes could return gdb.Value to return utils.Value instead. Change-Id: I2bb25a22305980f7439894a5fbc0099bdb569d7d Signed-off-by: xuxingliang --- tools/gdb/nuttxgdb/utils.py | 71 ++++++++++++++++++++++++++++++++++--- 1 file changed, 66 insertions(+), 5 deletions(-) diff --git a/tools/gdb/nuttxgdb/utils.py b/tools/gdb/nuttxgdb/utils.py index 8ddbf02fff8..4992eae40b4 100644 --- a/tools/gdb/nuttxgdb/utils.py +++ b/tools/gdb/nuttxgdb/utils.py @@ -18,6 +18,8 @@ # ############################################################################ +from __future__ import annotations + import argparse import importlib import json @@ -38,27 +40,86 @@ g_macro_ctx = None class Value(gdb.Value): - def __init__(self, obj: gdb.Value): + def __init__(self, obj: Union[gdb.Value, Value]): super().__init__(obj) + def __isabstractmethod__(self): + # Added to avoid getting error using __getattr__ + return False + def __getattr__(self, key): if hasattr(super(), key): - return Value(super().__getattribute__(key)) + value = super().__getattribute__(key) else: - return Value(super().__getitem__(key)) + value = super().__getitem__(key) + + return Value(value) if not isinstance(value, Value) else value def __getitem__(self, key): - return Value(super().__getitem__(key)) + value = super().__getitem__(key) + return Value(value) if not isinstance(value, Value) else value + + def __format__(self, format_spec: str) -> str: + try: + return super().__format__(format_spec) + except TypeError: + # Convert GDB value to python value, and then format it + type_code_map = { + gdb.TYPE_CODE_INT: int, + gdb.TYPE_CODE_PTR: int, + gdb.TYPE_CODE_ENUM: int, + gdb.TYPE_CODE_FUNC: hex, + gdb.TYPE_CODE_BOOL: bool, + gdb.TYPE_CODE_FLT: float, + gdb.TYPE_CODE_STRING: str, + gdb.TYPE_CODE_CHAR: lambda x: chr(int(x)), + } + + t = self.type + while t.code == gdb.TYPE_CODE_TYPEDEF: + t = t.target() + + type_code = t.code + try: + converter = type_code_map[type_code] + return f"{converter(self):{format_spec}}" + except KeyError: + raise TypeError( + f"Unsupported type: {self.type}, {self.type.code} {self}" + ) + + @property + def address(self) -> Value: + value = super().address + return value and Value(value) def cast(self, type: str | gdb.Type, ptr: bool = False) -> Optional["Value"]: try: - gdb_type = gdb.lookup_type(type) if isinstance(type, str) else type + gdb_type = lookup_type(type) if isinstance(type, str) else type if ptr: gdb_type = gdb_type.pointer() return Value(super().cast(gdb_type)) except gdb.error: return None + def dereference(self) -> Value: + return Value(super().dereference()) + + def reference_value(self) -> Value: + return Value(super().reference_value()) + + def referenced_value(self) -> Value: + return Value(super().referenced_value()) + + def rvalue_reference_value(self) -> Value: + return Value(super().rvalue_reference_value()) + + def const_value(self) -> Value: + return Value(super().const_value()) + + def dynamic_cast(self, type: gdb.Type) -> Value: + return Value(super().dynamic_cast(type)) + class Backtrace: """ -- Gitee From 4c47429d2b5a06b381d2055606caeab4a0603db2 Mon Sep 17 00:00:00 2001 From: xuxingliang Date: Fri, 8 Nov 2024 13:31:20 +0800 Subject: [PATCH 003/235] gdb/utils: cache backtrace result for better performance VELAPLATFO-42403 GDB is slow to look up symbols, cache the result to speed up commands like memdump etc. Change-Id: I7ebd988813925eb970fc2672d205297b1ddbf29b Signed-off-by: xuxingliang --- tools/gdb/nuttxgdb/utils.py | 25 +++++++++++++++++++++---- 1 file changed, 21 insertions(+), 4 deletions(-) diff --git a/tools/gdb/nuttxgdb/utils.py b/tools/gdb/nuttxgdb/utils.py index 4992eae40b4..56d2d416124 100644 --- a/tools/gdb/nuttxgdb/utils.py +++ b/tools/gdb/nuttxgdb/utils.py @@ -37,6 +37,7 @@ from .protocols.thread import Tcb g_symbol_cache = {} g_type_cache = {} g_macro_ctx = None +g_backtrace_cache = {} class Value(gdb.Value): @@ -152,10 +153,21 @@ class Backtrace: self, address: List[Union[gdb.Value, int]] = [], formatter="{:<5} {:<36} {}\n", + break_null=True, ): self.formatter = formatter # Address, Function, Source self._formatted = None # Cached formatted backtrace - self.backtrace = [res for addr in address if (res := self.convert(addr))] + self.backtrace = [] + for addr in address: + if break_null and not addr: + break + self.append(addr) + + def __eq__(self, value: Backtrace) -> bool: + return self.backtrace == value.backtrace + + def __hash__(self) -> int: + return hash(tuple(self.backtrace)) def append(self, addr: Union[gdb.Value, int]) -> None: """Append an address to the backtrace""" @@ -166,7 +178,10 @@ class Backtrace: def convert(self, addr: Union[gdb.Value, int]) -> Tuple[int, str, str]: """Convert an address to function and source""" if not addr: - return + return None + + if int(addr) in g_backtrace_cache: + return g_backtrace_cache[int(addr)] if type(addr) is int: addr = gdb.Value(addr) @@ -177,7 +192,9 @@ class Backtrace: func = addr.format_string(symbols=True, address=False) sym = gdb.find_pc_line(int(addr)) source = str(sym.symtab) + ":" + str(sym.line) - return (int(addr), func, source) + result = (int(addr), func, source) + g_backtrace_cache[int(addr)] = result + return result @property def formatted(self): @@ -974,7 +991,7 @@ class Addr2Line(gdb.Command): def print_backtrace(self, addresses, pid=None): if pid: gdb.write(f"\nBacktrace of {pid}\n") - backtraces = Backtrace(addresses, formatter=self.formatter) + backtraces = Backtrace(addresses, formatter=self.formatter, break_null=False) gdb.write(str(backtraces)) def invoke(self, args, from_tty): -- Gitee From 0147f8bde65cc42b8a5f1e1931ac51cc16b6ab89 Mon Sep 17 00:00:00 2001 From: Xu Xingliang Date: Fri, 1 Nov 2024 10:29:04 +0800 Subject: [PATCH 004/235] gdb: optimize memory commands VELAPLATFO-46132 Tested on a complex project, results are promising. Command Time cost(s) Time saving(s) Peformance Boost Before After memleak 39.494172 22.366415 17.127757 1.8 memdump 41.872441 26.458386 15.414055 1.6 memdump -a 0x1234 28.116294 1.114119 27.002175 25.2 memdump --no-backtrace N/A 1.114119 memmap 7.973809 6.836468 1.137341 1.2 Change-Id: I5729346eb81ddb3a60fa15b0ee897bf0b76a1ee1 Signed-off-by: Xu Xingliang --- tools/gdb/nuttxgdb/memdump.py | 1385 +++++++----------------- tools/gdb/nuttxgdb/mm.py | 637 +++++++++++ tools/gdb/nuttxgdb/prefix.py | 7 + tools/gdb/nuttxgdb/protocols/mm.py | 120 ++ tools/gdb/nuttxgdb/utils.py | 7 + tools/gdb/tests/test_runtime_memory.py | 26 +- 6 files changed, 1201 insertions(+), 981 deletions(-) create mode 100644 tools/gdb/nuttxgdb/mm.py create mode 100644 tools/gdb/nuttxgdb/protocols/mm.py diff --git a/tools/gdb/nuttxgdb/memdump.py b/tools/gdb/nuttxgdb/memdump.py index 82ce8a34a0c..8652fa4f833 100644 --- a/tools/gdb/nuttxgdb/memdump.py +++ b/tools/gdb/nuttxgdb/memdump.py @@ -20,894 +20,352 @@ import argparse import bisect +import json import time +from collections import defaultdict +from os import path +from typing import Dict, Generator, List, Protocol, Tuple import gdb -from . import utils -from .lists import NxSQueue, sq_count -from .utils import get_long_type, get_symbol_value, get_tcb, lookup_type, read_ulong - -MM_ALLOC_BIT = 0x1 -MM_PREVFREE_BIT = 0x2 -MM_MASK_BIT = MM_ALLOC_BIT | MM_PREVFREE_BIT -MEMPOOL_MAGIC_ALLOC = 0x55555555 - -PID_MM_ORPHAN = -6 -PID_MM_BIGGEST = -5 -PID_MM_FREE = -4 -PID_MM_ALLOC = -3 -PID_MM_LEAK = -2 -PID_MM_MEMPOOL = -1 - -mm_allocnode_type = lookup_type("struct mm_allocnode_s") -sizeof_size_t = lookup_type("size_t").sizeof -sizeof_sq_entry_t = lookup_type("sq_entry_t").sizeof -mempool_backtrace_type = lookup_type("struct mempool_backtrace_s") -mempool_s_type = utils.lookup_type("struct mempool_s") -mempool_procfs_entry_type = utils.lookup_type("struct mempool_procfs_entry_s") - -CONFIG_MM_BACKTRACE = get_symbol_value("CONFIG_MM_BACKTRACE") -CONFIG_MM_DFAULT_ALIGNMENT = get_symbol_value("CONFIG_MM_DFAULT_ALIGNMENT") - - -def align_up(size, align) -> int: - """Align the size to the specified alignment""" - return (size + (align - 1)) & ~(align - 1) - - -def mm_nodesize(size) -> int: - """Return the real size of a memory node""" - return size & ~MM_MASK_BIT - - -def mm_node_is_alloc(size) -> bool: - """Return node is allocated according to recorded size""" - return size & MM_ALLOC_BIT != 0 - - -def mm_prevnode_is_free(size) -> bool: - """Return prevnode is free according to recorded size""" - return size & MM_PREVFREE_BIT != 0 - - -def mm_foreach(heap): - """Iterate over a heap, yielding each node""" - nregions = get_symbol_value("CONFIG_MM_REGIONS") - heapstart = heap["mm_heapstart"] - heapend = heap["mm_heapend"] - - for region in range(0, nregions): - start = heapstart[region] - end = heapend[region] - node = start - while node <= end: - yield node - next = int(node) + mm_nodesize(node["size"]) - next = gdb.Value(next).cast(mm_allocnode_type.pointer()) - if node == next: - gdb.write(f"Error: maybe have memory fault on {hex(node)}\n") - break - node = next - - -def mm_dumpnode(node, count, align, simple, detail, alive): - if node["size"] & MM_ALLOC_BIT != 0: - charnode = int(node) - if not alive: - # if pid is not alive put a red asterisk. - gdb.write("\x1b[33;1m*\x1b[m") - - if not detail: - gdb.write("%*d" % (6 if alive else 5, count)) - - gdb.write( - "%6d%12u%12u%#*x" - % ( - node["pid"], - mm_nodesize(node["size"]), - node["seqno"], - align, - charnode + mm_allocnode_type.sizeof, - ) +from . import mm, utils + + +class MMNodeDump(Protocol): + """Node information protocol for dump""" + + address: int # Note that address should be in type of int + nodesize: int + seqno: int + pid: int + backtrace: Tuple[int] + is_free: bool + from_pool: bool + overhead: int + + def contains(self, addr: int) -> bool: ... + + def read_memory(self) -> memoryview: ... + + +def dump_nodes( + heaps: List[mm.MMHeap], + pid=None, + nodesize=None, + used=None, + free=None, + seqmin=None, + seqmax=None, + orphan=None, + no_heap=False, + no_pool=False, + no_pid=None, +) -> Generator[MMNodeDump, None, None]: + def filter_node(node: MMNodeDump) -> bool: + return ( + (pid is None or node.pid == pid) + and (no_pid is None or node.pid != no_pid) + and (nodesize is None or node.nodesize == nodesize) + and (not used or not node.is_free) + and (not free or node.is_free) + and (seqmin is None or node.seqno >= seqmin) + and (seqmax is None or node.seqno <= seqmax) + and (not orphan or node.is_orphan) ) - if node.type.has_key("backtrace"): - firstrow = True - for backtrace in utils.ArrayIterator(node["backtrace"]): - if int(backtrace) == 0: - break + if not no_heap: + yield from (node for heap in heaps for node in filter(filter_node, heap.nodes)) - if simple: - gdb.write(" %0#*x" % (align, int(backtrace))) - else: - if firstrow: - firstrow = False - else: - if not detail: - gdb.write(" " * 6) - gdb.write(" " * (6 + 12 + 12 + align)) - gdb.write( - " [%0#*x] %-20s %s:%d\n" - % ( - align, - int(backtrace), - backtrace.format_string( - raw=False, symbols=True, address=False - ), - gdb.find_pc_line(int(backtrace)).symtab, - gdb.find_pc_line(int(backtrace)).line, - ) - ) - - else: - charnode = int(node) - gdb.write( - "%12u%#*x" - % ( - mm_nodesize(node["size"]), - align, - charnode + mm_allocnode_type.sizeof, - ) + if not no_pool: + yield from ( + blk + for pool in mm.get_pools(heaps) + for blk in filter(filter_node, pool.blks) ) - gdb.write("\n") - - -def mempool_multiple_foreach(mpool): - """Iterate over all pools in a mempool, yielding each pool""" - i = 0 - while i < mpool["npools"]: - pool = mpool["pools"] + i - yield pool - i += 1 - - -def mempool_align() -> int: - if CONFIG_MM_DFAULT_ALIGNMENT: - align = CONFIG_MM_DFAULT_ALIGNMENT - else: - align = 2 * sizeof_size_t - return align - - -def mempool_realblocksize(pool): - """Return the real block size of a mempool""" - - if CONFIG_MM_BACKTRACE >= 0: - return align_up( - pool["blocksize"] + mempool_backtrace_type.sizeof, - mempool_align(), - ) - else: - return pool["blocksize"] - - -def get_backtrace(node): - - backtrace_list = [] - max = node["backtrace"].type.range()[1] - for x in range(0, max): - if node["backtrace"][x] != 0: - backtrace_list.append(int(node["backtrace"][x])) - else: - break - - return tuple(backtrace_list) - - -def record_backtrace(node, size, backtrace_dict): - if node.type.has_key("backtrace"): - backtrace = get_backtrace(node) - if (backtrace, int(node["pid"])) not in backtrace_dict.keys(): - info = {} - info["node"] = node - info["count"] = 1 - info["size"] = size - info["pid"] = node["pid"] - backtrace_dict[(backtrace, int(node["pid"]))] = info - else: - backtrace_dict[(backtrace, int(node["pid"]))]["count"] += 1 - - return backtrace_dict - - -def get_count(element): - return element["count"] - -def mempool_foreach(pool): - """Iterate over all block in a mempool""" +def group_nodes( + nodes: List[MMNodeDump], grouped: Dict[MMNodeDump, List[MMNodeDump]] = None +) -> Dict[MMNodeDump, List[MMNodeDump]]: + grouped = grouped or defaultdict(list) + for node in nodes: + grouped[node].append(node) + return grouped - sq_entry_type = lookup_type("sq_entry_t") - - blocksize = mempool_realblocksize(pool) - if pool["ibase"] != 0: - nblk = pool["interruptsize"] / blocksize - while nblk > 0: - bufaddr = gdb.Value(pool["ibase"] + nblk * blocksize + pool["blocksize"]) - buf = bufaddr.cast(mempool_backtrace_type.pointer()) - yield buf - nblk -= 1 - - for entry in NxSQueue(pool["equeue"]): - nblk = (pool["expandsize"] - sq_entry_type.sizeof) / blocksize - base = int(entry) - nblk * blocksize - while nblk > 0: - nblk -= 1 - bufaddr = gdb.Value(base + nblk * blocksize + pool["blocksize"]) - buf = bufaddr.cast(mempool_backtrace_type.pointer()) - yield buf - - -def mempool_dumpbuf(buf, blksize, count, align, simple, detail, alive): - charnode = gdb.Value(buf).cast(lookup_type("char").pointer()) - - if not alive: - # if pid is not alive put a red asterisk. - gdb.write("\x1b[33;1m*\x1b[m") - - if not detail: - gdb.write("%*d" % (6 if alive else 5, count)) +def print_node(node: MMNodeDump, alive, count=1, formatter=None, no_backtrace=False): + formatter = formatter or "{:>1} {:>4} {:>12} {:>12} {:>12} {:>14} {:>18} {:}\n" gdb.write( - "%6d%12u%12u%#*x" - % ( - buf["pid"], - blksize, - buf["seqno"], - align, - (int)(charnode - blksize), + formatter.format( + "\x1b[33;1m*\x1b[m" if not alive else "", + "P" if node.from_pool else "H", + count, + node.pid, + node.nodesize, + node.seqno, + hex(node.address), + "", ) ) - if buf.type.has_key("backtrace"): - max = buf["backtrace"].type.range()[1] - firstrow = True - for x in range(0, max): - backtrace = int(buf["backtrace"][x]) - if backtrace == 0: - break - - if simple: - gdb.write(" %0#*x" % (align, backtrace)) - else: - if firstrow: - firstrow = False - else: - if not detail: - gdb.write(" " * 6) - gdb.write(" " * (6 + 12 + 12 + align)) - gdb.write( - " [%0#*x] %-20s %s:%d\n" - % ( - align, - int(backtrace), - buf["backtrace"][x].format_string( - raw=False, symbols=True, address=False - ), - gdb.find_pc_line(int(backtrace)).symtab, - gdb.find_pc_line(int(backtrace)).line, - ) - ) - - gdb.write("\n") + if mm.CONFIG_MM_BACKTRACE and not no_backtrace: + leading = formatter.format("", "", "", "", "", "", "", "")[:-1] + btformat = leading + "{1:<48}{2}\n" + if node.backtrace and node.backtrace[0]: + gdb.write(f"{utils.Backtrace(node.backtrace, formatter=btformat)}\n") -def check_node_alive(node) -> bool: - if CONFIG_MM_BACKTRACE <= 0: - return True - else: - tcb = get_tcb(node["pid"]) - return tcb is not None +def print_header(formatter=None): + formatter = formatter or "{:>1} {:>4} {:>12} {:>12} {:>12} {:>14} {:>18} {:}\n" + head = ("", "Pool", "CNT", "PID", "Size", "Seqno", "Address", "Backtrace") + gdb.write(formatter.format(*head)) -class HeapNode: - def __init__(self, gdb_node, nextfree=False): - self.gdb_node = gdb_node +def get_heaps(args_heap=None) -> List[mm.MMHeap]: + if args_heap: + return [mm.MMHeap(gdb.parse_and_eval(args_heap))] + return mm.get_heaps() - record_size = gdb_node["size"] - - try: - seqno = gdb_node["seqno"] - except gdb.error: - seqno = 0 - - try: - node_pid = gdb_node["pid"] - except gdb.error: - node_pid = 0 - - self.size = mm_nodesize(record_size) - self.alloc = mm_node_is_alloc(record_size) - self.seqno = seqno - self.pid = node_pid - self.alive = check_node_alive(gdb_node) - self.base = int(gdb_node) - self.prevfree = mm_prevnode_is_free(record_size) - self.nextfree = nextfree - - def __lt__(self, other): - return self.size < other.size - - def inside_sequence(self, seqmin, seqmax): - return self.seqno >= seqmin and self.seqno <= seqmax - - def contains_address(self, address): - return address >= self.base and address < self.base + self.size - - def is_orphan(self): - return self.prevfree or self.nextfree - - def dump(self, detail, simple, align, backtrace_dict): - if detail: - mm_dumpnode( - self.gdb_node, - 1, - align, - simple, - detail, - self.alive, - ) - else: - backtrace_dict = record_backtrace(self.gdb_node, self.size, backtrace_dict) - -class Memdump(gdb.Command): - """Dump the heap and mempool memory""" +class MMDump(gdb.Command): + """Dump memory manager heap""" def __init__(self): - super().__init__("memdump", gdb.COMMAND_USER) - - def mempool_dump(self, mpool, pid, seqmin, seqmax, address, simple, detail): - """Dump the mempool memory""" - for pool in mempool_multiple_foreach(mpool): - if pid == PID_MM_FREE: - for entry in NxSQueue(pool["queue"]): - gdb.write("%12u%#*x\n" % (pool["blocksize"], self.align, entry)) - self.aordblks += 1 - self.uordblks += mempool_realblocksize(pool) - - for entry in NxSQueue(pool["iqueue"]): - gdb.write("%12u%#*x\n" % (pool["blocksize"], self.align, entry)) - self.aordblks += 1 - self.uordblks += mempool_realblocksize(pool) - else: - if not mempool_backtrace_type: - return True - - for buf in mempool_foreach(pool): - if ( - (pid == buf["pid"] or pid == PID_MM_ALLOC) - and (buf["seqno"] >= seqmin and buf["seqno"] < seqmax) - and buf["magic"] == MEMPOOL_MAGIC_ALLOC - ): - charnode = int(buf) - if detail: - mempool_dumpbuf( - buf, - pool["blocksize"], - 1, - self.align, - simple, - detail, - check_node_alive(buf), - ) - else: - self.backtrace_dict = record_backtrace( - buf, pool["blocksize"], self.backtrace_dict - ) - if address and ( - address < charnode - and address >= charnode - pool["blocksize"] - ): - mempool_dumpbuf( - buf, - pool["blocksize"], - 1, - self.align, - simple, - detail, - check_node_alive(buf), - ) - gdb.write( - "\nThe address 0x%x found belongs to" - "the mempool node with base address 0x%x\n" - % (address, charnode) - ) - print_node = "p *(struct mempool_backtrace_s *)0x%x" % ( - charnode - ) - gdb.write(print_node + "\n") - gdb.execute(print_node) - return True - self.aordblks += 1 - self.uordblks += mempool_realblocksize(pool) - return False - - def memnode_dump(self, node): - self.aordblks += 1 - self.uordblks += node.size - node.dump( - detail=self.detail, - simple=self.simple, - align=self.align, - backtrace_dict=self.backtrace_dict, + super().__init__("mm dump", gdb.COMMAND_USER) + # define memdump as mm dump + utils.alias("memdump", "mm dump") + + def find(self, heaps: List[mm.MMHeap], addr): + """Find the node that contains the address""" + # Search pools firstly. + for pool in mm.get_pools(heaps): + if blk := pool.find(addr): + return blk + + # Search heaps + for heap in heaps: + if node := heap.find(addr): + return node + + def parse_args(self, arg): + parser = argparse.ArgumentParser(description=self.__doc__) + parser.add_argument( + "-a", + "--address", + type=str, + default=None, + help="The address to inspect", ) - def memdump_tail(self, detail, simple): - if not detail: - output = [v for v in self.backtrace_dict.values()] - output.sort(key=get_count, reverse=True) - for node in output: - if node["node"].type == mm_allocnode_type.pointer(): - mm_dumpnode( - node["node"], - node["count"], - self.align, - simple, - detail, - check_node_alive(node), - ) - else: - mempool_dumpbuf( - node["node"], - node["size"], - node["count"], - self.align, - simple, - detail, - check_node_alive(node), - ) - - gdb.write("%12s%12s\n" % ("Total Blks", "Total Size")) - gdb.write("%12d%12d\n" % (self.aordblks, self.uordblks)) - - def memdump(self, pid, seqmin, seqmax, address, simple, detail, biggest_top=30): - """Dump the heap memory""" - - self.simple = simple - self.detail = detail - - alloc_node = [] - free_node = [] - mempool_node = [] - - heap = gdb.parse_and_eval("g_mmheap") - if heap.type.has_key("mm_mpool"): - if self.mempool_dump( - heap["mm_mpool"], pid, seqmin, seqmax, address, simple, detail - ): - return - - prev_node = None - - for gdb_node in mm_foreach(heap): - node = HeapNode(gdb_node) - - if prev_node: - prev_node.nextfree = not node.alloc - - prev_node = node - - if not node.inside_sequence(seqmin, seqmax): - continue - - if address: - if node.contains_address(address): - gdb.write( - "\nThe address 0x%x found belongs to" - "the memory node with base address 0x%x\n" - % (address, node.base) - ) - print_node = "p *(struct mm_allocnode_s *)0x%x" % (node.base) - gdb.write(print_node + "\n") - gdb.execute(print_node) - return - - if node.pid == PID_MM_MEMPOOL: - mempool_node.append(node) - elif node.alloc: - alloc_node.append(node) - else: - free_node.append(node) - - title_dict = { - PID_MM_MEMPOOL: "Dump mempool:\n", - PID_MM_ALLOC: "Dump all used memory node info, use '\x1b[33;1m*\x1b[m' mark pid is not exist:\n", - PID_MM_FREE: "Dump all free memory node info:\n", - PID_MM_BIGGEST: f"Dump biggest allocated top {biggest_top}\n", - PID_MM_ORPHAN: "Dump allocated orphan nodes\n", - } - - if pid in title_dict.keys(): - title = title_dict[pid] - elif pid >= 0: - title = title_dict[PID_MM_ALLOC] - else: - title = "Dump unspecific\n" - - gdb.write(title) - if not detail: - gdb.write("%6s" % ("CNT")) - gdb.write( - "%6s%12s%12s%8s%8s%8s\n" - % ("PID", "Size", "Sequence", str(self.align), "Address", "Callstack") + parser.add_argument( + "--heap", + type=str, + default=None, + help="Which heap to inspect", ) - if pid == PID_MM_FREE: - self.detail = True - for node in free_node: - self.memnode_dump(node) - elif pid == PID_MM_ALLOC: - for node in alloc_node: - self.memnode_dump(node) - elif pid == PID_MM_BIGGEST: - sorted_alloc = sorted(alloc_node)[-biggest_top:] - for node in sorted_alloc: - self.memnode_dump(node) - elif pid == PID_MM_ORPHAN: - for node in alloc_node: - if node.is_orphan(): - self.memnode_dump(node) - elif pid == PID_MM_MEMPOOL: - for node in mempool_node: - self.memnode_dump(node) - elif pid >= 0: - for node in alloc_node: - if node.pid == pid: - self.memnode_dump(node) - - self.memdump_tail(detail, simple) - - def complete(self, text, word): - return gdb.COMPLETE_SYMBOL - - def parse_arguments(self, argv): - parser = argparse.ArgumentParser(description="memdump command") - parser.add_argument("-p", "--pid", type=str, help="Thread PID, -1 for mempool") - parser.add_argument("-a", "--addr", type=str, help="Query memory address") - parser.add_argument("-i", "--min", type=str, help="Minimum value") - parser.add_argument("-x", "--max", type=str, help="Maximum value") - parser.add_argument("--used", action="store_true", help="Used flag") + parser.add_argument( + "-p", "--pid", type=int, default=None, help="Thread PID, -1 for mempool" + ) + parser.add_argument( + "-i", "--min", type=int, default=None, help="Minimum sequence number" + ) + parser.add_argument( + "-x", "--max", type=int, default=None, help="Maximum sequence number" + ) parser.add_argument("--free", action="store_true", help="Free flag") parser.add_argument("--biggest", action="store_true", help="biggest allocated") - parser.add_argument("--top", type=str, help="biggest top n, default 30") parser.add_argument( - "--orphan", action="store_true", help="orphan allocated(neighbor of free)" + "--orphan", action="store_true", help="Filter nodes that are orphan" + ) + parser.add_argument( + "--top", type=int, default=None, help="biggest top n, default to all" + ) + parser.add_argument( + "--size", type=int, default=None, help="Node block size filter." ) parser.add_argument( - "-d", - "--detail", + "--no-pool", + "--nop", action="store_true", - help="Output details of each node", - default=False, + help="Exclude dump from memory pool", ) parser.add_argument( - "-s", - "--simple", + "--no-heap", "--noh", action="store_true", help="Exclude heap dump" + ) + parser.add_argument( + "--no-group", "--nog", action="store_true", help="Do not group the nodes" + ) + parser.add_argument( + "--no-backtrace", + "--nob", action="store_true", - help="Simplified Output", - default=False, + help="Do not print backtrace", + ) + + # add option to sort the node by size or count + parser.add_argument( + "--sort", + type=str, + choices=["size", "nodesize", "count", "seq", "address"], + default="count", + help="sort the node by size(nodesize * count), nodesize, count or sequence number", ) - if argv[0] == "": - argv = None try: - args = parser.parse_args(argv) + return parser.parse_args(gdb.string_to_argv(arg)) except SystemExit: - return None - - return { - "pid": int(args.pid, 0) if args.pid else None, - "seqmin": int(args.min, 0) if args.min else 0, - "seqmax": int(args.max, 0) if args.max else 0xFFFFFFFF, - "used": args.used, - "free": args.free, - "addr": int(utils.parse_arg(args.addr)) if args.addr else None, - "simple": args.simple, - "detail": args.detail, - "biggest": args.biggest, - "orphan": args.orphan, - "top": int(args.top) if args.top else 30, - } - - def invoke(self, args, from_tty): - if sizeof_size_t == 4: - self.align = 11 - else: - self.align = 19 - - arg = self.parse_arguments(args.split(" ")) - - if arg is None: return - pid = PID_MM_ALLOC - if arg["used"]: - pid = PID_MM_ALLOC - elif arg["free"]: - pid = PID_MM_FREE - elif arg["biggest"]: - pid = PID_MM_BIGGEST - elif arg["orphan"]: - pid = PID_MM_ORPHAN - elif arg["pid"]: - pid = arg["pid"] - if CONFIG_MM_BACKTRACE <= 0: - arg["detail"] = True - - self.aordblks = 0 - self.uordblks = 0 - self.backtrace_dict = {} - self.memdump( - pid, - arg["seqmin"], - arg["seqmax"], - arg["addr"], - arg["simple"], - arg["detail"], - arg["top"], - ) - - -class Memleak(gdb.Command): - """Memleak check""" - - def __init__(self): - self.elf = utils.import_check( - "elftools.elf.elffile", "ELFFile", "Plase pip install pyelftools\n" - ) - if not self.elf: + def invoke(self, arg: str, from_tty: bool) -> None: + if not (args := self.parse_args(arg)): return - super().__init__("memleak", gdb.COMMAND_USER) + heaps = ( + [mm.MMHeap(gdb.parse_and_eval(args.heap))] if args.heap else mm.get_heaps() + ) + pids = [int(tcb["pid"]) for tcb in utils.get_tcbs()] - def next_ptr(self): - inf = gdb.selected_inferior() - heap = gdb.parse_and_eval("g_mmheap") - longsize = get_long_type().sizeof - region = get_symbol_value("CONFIG_MM_REGIONS") - regions = [] + print_header() - for i in range(0, region): - start = int(heap["mm_heapstart"][i]) - end = int(heap["mm_heapend"][i]) - regions.append({"start": start, "end": end}) + def printnode(node, count): + print_node(node, node.pid in pids, count, no_backtrace=args.no_backtrace) - # Search global variables - for objfile in gdb.objfiles(): - gdb.write(f"Searching global symbol in: {objfile.filename}\n") - elf = self.elf.load_from_path(objfile.filename) - symtab = elf.get_section_by_name(".symtab") - for symbol in symtab.iter_symbols(): - if symbol["st_info"]["type"] != "STT_OBJECT": - continue + if args.address: + addr = int(gdb.parse_and_eval(args.address)) + # Address specified, find and return directly. + node = None + for pool in mm.get_pools(heaps): + if node := pool.find(addr): + break - if symbol["st_size"] < longsize: - continue + if node or (node := self.find(heaps, addr)): + printnode(node, 1) + source = "Pool" if node.from_pool else "Heap" + print(f"{addr: #x} found belongs to {source}, node@{node.address:#x}") + else: + print(f"Address {addr:#x} not found in any heap") + return - global_size = symbol["st_size"] // longsize * longsize - global_mem = inf.read_memory(symbol["st_value"], global_size) - while global_size: - global_size = global_size - longsize - ptr = read_ulong(global_mem, global_size) - for region in regions: - if ptr >= region["start"] and ptr < region["end"]: - yield ptr - break - - gdb.write("Searching in grey memory\n") - for node in self.grey_list: - addr = node["addr"] - mem = inf.read_memory(addr, node["size"]) - i = 0 - while i < node["size"]: - ptr = read_ulong(mem, i) - for region in regions: - if ptr >= region["start"] and ptr < region["end"]: - yield ptr - break - i = i + longsize - - def collect_white_dict(self): - white_dict = {} - allocnode_size = mm_allocnode_type.sizeof - - # collect all user malloc ptr - - heap = gdb.parse_and_eval("g_mmheap") - for node in mm_foreach(heap): - if node["size"] & MM_ALLOC_BIT != 0 and node["pid"] != PID_MM_MEMPOOL: - addr = int(node) + allocnode_size - - node_dict = {} - node_dict["node"] = node - node_dict["size"] = mm_nodesize(node["size"]) - allocnode_size - node_dict["addr"] = addr - white_dict[int(addr)] = node_dict - - if heap.type.has_key("mm_mpool"): - for pool in mempool_multiple_foreach(heap["mm_mpool"]): - for buf in mempool_foreach(pool): - if buf["magic"] == MEMPOOL_MAGIC_ALLOC: - addr = int(buf) - pool["blocksize"] - - buf_dict = {} - buf_dict["node"] = buf - buf_dict["size"] = pool["blocksize"] - buf_dict["addr"] = addr - white_dict[int(addr)] = buf_dict - - return white_dict + filters = { + "pid": args.pid, + "nodesize": args.size, + "used": not args.free, + "free": args.free, + "seqmin": args.min, + "seqmax": args.max, + "orphan": args.orphan, + } - def parse_arguments(self, argv): - parser = argparse.ArgumentParser(description="memleak command") - parser.add_argument( - "-s", - "--simple", - action="store_true", - help="Simplified Output", - default=False, - ) - parser.add_argument( - "-d", - "--detail", - action="store_true", - help="Output details of each node", - default=False, - ) + heap_nodes = dump_nodes(heaps, **filters, no_heap=args.no_heap, no_pool=True) + pool_nodes = dump_nodes(heaps, **filters, no_heap=True, no_pool=args.no_pool) - if argv[0] == "": - argv = None - try: - args = parser.parse_args(argv) - except SystemExit: - return None - - return {"simple": args.simple, "detail": args.detail} + if args.biggest: + # Find the biggest nodes, only applicable to heaps + nodes = sorted( + heap_nodes, + key=lambda node: node.nodesize, + reverse=True, + ) + for node in nodes[: args.top]: + print(f"node@{node.address}: {node}") + return - def diagnose(self, *args, **kwargs): - output = gdb.execute("memleak", to_string=True) - return { - "title": "Memory Leak Report", - "command": "memleak", - "details": output, + sort_method = { + "count": lambda node: 1, + "size": lambda node: node.nodesize, + "nodesize": lambda node: node.nodesize, + "seq": lambda node: node.seqno, + "address": lambda node: node.address, } - def invoke(self, args, from_tty): - if sizeof_size_t == 4: - align = 11 - else: - align = 19 + def sort_nodes(nodes): + nodes = sorted(nodes, key=sort_method[args.sort], reverse=True) + if args.top is not None: + nodes = nodes[: args.top] if args.top > 0 else nodes[args.top :] + return nodes - arg = self.parse_arguments(args.split(" ")) + if args.no_group: + # Print nodes without grouping + nodes = list(heap_nodes) + nodes.extend(pool_nodes) - if arg is None: - return + for node in sort_nodes(nodes): + printnode(node, 1) - if CONFIG_MM_BACKTRACE < 0: - gdb.write("Need to set CONFIG_MM_BACKTRACE to 8 or 16 better.\n") + gdb.write(f"Total blks: {len(nodes)}\n") return - elif CONFIG_MM_BACKTRACE == 0: - gdb.write("CONFIG_MM_BACKTRACE is 0, no backtrace available\n") - start = last = time.time() - white_dict = self.collect_white_dict() + # Finally group the nodes and then print - self.grey_list = [] - gdb.write("Searching for leaked memory, please wait a moment\n") - last = time.time() + grouped: Dict[MMNodeDump, MMNodeDump] = defaultdict(list) + grouped = group_nodes(heap_nodes) + grouped = group_nodes(pool_nodes, grouped) - sorted_keys = sorted(white_dict.keys()) - for ptr in self.next_ptr(): - # Find a closest addres in white_dict - pos = bisect.bisect_right(sorted_keys, ptr) - if pos == 0: - continue - grey_key = sorted_keys[pos - 1] - if grey_key in white_dict and ptr < grey_key + white_dict[grey_key]["size"]: - self.grey_list.append(white_dict[grey_key]) - del white_dict[grey_key] + # Replace the count and size to count grouped nodes + sort_method["count"] = lambda node: len(grouped[node]) + sort_method["size"] = lambda node: node.nodesize * len(grouped[node]) + total_blk = total_size = 0 + for node in sort_nodes(grouped.keys()): + count = len(grouped[node]) + total_blk += count + if node.pid != mm.PID_MM_MEMPOOL: + total_size += count * node.nodesize + printnode(node, count) - # All white node is leak + print(f"Total {total_blk} blks, {total_size} bytes") - gdb.write(f"Search all memory use {(time.time() - last):.2f} seconds\n") - - gdb.write("\n") - if len(white_dict) == 0: - gdb.write("All node have references, no memory leak!\n") - return - gdb.write("Leak catch!, use '\x1b[33;1m*\x1b[m' mark pid is not exist:\n") +class MMfrag(gdb.Command): + """Show memory fragmentation rate""" - if CONFIG_MM_BACKTRACE > 0 and not arg["detail"]: - gdb.write("%6s" % ("CNT")) + def __init__(self): + super().__init__("mm frag", gdb.COMMAND_USER) + utils.alias("memfrag", "mm frag") - gdb.write( - "%6s%12s%12s%*s %s\n" - % ("PID", "Size", "Sequence", align, "Address", "Callstack") + def invoke(self, args, from_tty): + parser = argparse.ArgumentParser(description=self.__doc__) + parser.add_argument( + "--heap", + type=str, + default=None, + help="Which heap to inspect", ) - if CONFIG_MM_BACKTRACE > 0 and not arg["detail"]: - - # Filter same backtrace + try: + args = parser.parse_args(gdb.string_to_argv(args)) + except SystemExit: + return None - backtrace_dict = {} - for addr in white_dict.keys(): - backtrace_dict = record_backtrace( - white_dict[addr]["node"], white_dict[addr]["size"], backtrace_dict - ) + for heap in get_heaps(args.heap): + nodes = list( + sorted(heap.nodes_free(), key=lambda node: node.nodesize, reverse=True) + ) + if not nodes: + gdb.write(f"{heap}: no free nodes\n") + continue - leaksize = 0 - leaklist = [] - for node in backtrace_dict.values(): - leaklist.append(node) - - # sort by count - leaklist.sort(key=get_count, reverse=True) - - i = 0 - for node in leaklist: - if node["node"].type == mm_allocnode_type.pointer(): - mm_dumpnode( - node["node"], - node["count"], - align, - arg["simple"], - arg["detail"], - check_node_alive(node), - ) - else: - mempool_dumpbuf( - node["node"], - node["size"], - node["count"], - align, - arg["simple"], - arg["detail"], - check_node_alive(node), - ) - - leaksize += node["count"] * node["size"] - i += 1 + freesize = sum(node.nodesize for node in nodes) + remaining = freesize + fragrate = 0 - gdb.write( - f"Alloc {len(white_dict)} count,\ -have {i} some backtrace leak, total leak memory is {int(leaksize)} bytes\n" - ) - else: - leaksize = 0 - for node in white_dict.values(): - if node["node"].type == mm_allocnode_type.pointer(): - mm_dumpnode( - node["node"], - 1, - align, - arg["simple"], - True, - check_node_alive(node), - ) - else: - mempool_dumpbuf( - node["node"], - node["size"], - 1, - align, - arg["simple"], - True, - check_node_alive(node), - ) - leaksize += node["size"] + for node in nodes: + fragrate += (1 - (node.nodesize / remaining)) * ( + node.nodesize / freesize + ) + remaining -= node.nodesize + fragrate = fragrate * 1000 gdb.write( - f"Alloc {len(white_dict)} count, total leak memory is {int(leaksize)} bytes\n" + f"{heap.name}@{heap.address:#x}, fragmentation rate:{fragrate:.2f}," + f" heapsize: {heap.heapsize}, free size: {freesize}," + f" free count: {len(nodes)}, largest: {nodes[0].nodesize}\n" ) - gdb.write(f"Finished in {(time.time() - start):.2f} seconds\n") +class MMMap(gdb.Command): + """Generate memory map image to visualize memory layout""" -class Memmap(gdb.Command): def __init__(self): self.np = utils.import_check("numpy", errmsg="Please pip install numpy\n") self.plt = utils.import_check( @@ -917,198 +375,185 @@ class Memmap(gdb.Command): if not self.np or not self.plt or not self.math: return - super().__init__("memmap", gdb.COMMAND_USER) - - def save_memory_map(self, mallinfo, output_file): - mallinfo = sorted(mallinfo, key=lambda item: item["addr"]) - start = mallinfo[0]["addr"] - size = mallinfo[-1]["addr"] - start + super().__init__("mm map", gdb.COMMAND_USER) + utils.alias("memmap", "mm map") + def save_memory_map(self, nodes: List[MMNodeDump], output_file): + mallinfo = sorted(nodes, key=lambda node: node.address) + start = mallinfo[0].address + size = mallinfo[-1].address - start order = self.math.ceil(size**0.5) img = self.np.zeros([order, order]) for node in mallinfo: - addr = node["addr"] - size = node["size"] + addr = node.address + size = node.nodesize start_index = addr - start end_index = start_index + size - img.flat[start_index:end_index] = 1 + self.math.log2(node["sequence"] + 1) + img.flat[start_index:end_index] = 1 + self.math.log2(node.seqno + 1) self.plt.imsave(output_file, img, cmap=self.plt.get_cmap("Greens")) - def allocinfo(self): - info = [] - heap = gdb.parse_and_eval("g_mmheap") - for node in mm_foreach(heap): - if node["size"] & MM_ALLOC_BIT != 0: - allocnode = gdb.Value(node).cast(lookup_type("char").pointer()) - info.append( - { - "addr": int(allocnode), - "size": int(mm_nodesize(node["size"])), - "sequence": int(node["seqno"]), - } - ) - return info - def parse_arguments(self, argv): - parser = argparse.ArgumentParser(description="memdump command") + parser = argparse.ArgumentParser(description=self.__doc__) + parser.add_argument( + "-o", "--output", type=str, default=None, help="img output file" + ) parser.add_argument( - "-o", "--output", type=str, default="memmap", help="img output file" + "--heap", type=str, help="Which heap's pool to show", default=None ) - if argv[0] == "": - argv = None + try: args = parser.parse_args(argv) except SystemExit: return None - return args.output + + return args def invoke(self, args, from_tty): - output_file = self.parse_arguments(args.split(" ")) - meminfo = self.allocinfo() - self.save_memory_map(meminfo, output_file + ".png") + if not (args := self.parse_arguments(gdb.string_to_argv(args))): + return + for heap in get_heaps(args.heap): + name = heap.name or f"heap@{heap.address:#x}" + output = args.output or f"{name}.png" + self.save_memory_map(heap.nodes_used(), output) + gdb.write(f"Memory map saved to {output}\n") -class Memfrag(gdb.Command): - def __init__(self): - super().__init__("memfrag", gdb.COMMAND_USER) - def parse_arguments(self, argv): - parser = argparse.ArgumentParser(description="memfrag command") - parser.add_argument( - "-d", "--detail", action="store_true", help="Output details" - ) - if argv[0] == "": - argv = None - try: - args = parser.parse_args(argv) - except SystemExit: - return None - return args.detail - - def freeinfo(self): - info = [] - heap = gdb.parse_and_eval("g_mmheap") - for node in mm_foreach(heap): - if node["size"] & MM_ALLOC_BIT == 0: - freenode = gdb.Value(node).cast(lookup_type("char").pointer()) - info.append( - { - "addr": int(freenode), - "size": int(mm_nodesize(node["size"])), - } - ) - return info +class GlobalNode(MMNodeDump): + def __init__(self, address: int, nodesize: int): + self.address = address + self.nodesize = nodesize + self.pid = None + self.seqno = None + self.overhead = 0 + self.backtrace = () - def invoke(self, args, from_tty): - detail = self.parse_arguments(args.split(" ")) - info = self.freeinfo() - - info = sorted(info, key=lambda item: item["size"], reverse=True) - if detail: - for node in info: - gdb.write(f"addr: {node['addr']}, size: {node['size']}\n") - - heapsize = gdb.parse_and_eval("*g_mmheap")["mm_heapsize"] - freesize = sum(node["size"] for node in info) - remaining = freesize - fragrate = 0 - - for node in info: - fragrate += (1 - (node["size"] / remaining)) * (node["size"] / freesize) - remaining -= node["size"] - - fragrate = fragrate * 1000 - gdb.write(f"memory fragmentation rate: {fragrate:.2f}\n") - gdb.write( - f"heap size: {heapsize}, free size: {freesize}, uordblks:" - f"{info.__len__()} largest block: {info[0]['size']} \n" - ) + def __repr__(self): + return f"GlobalVar@{self.address:x}:{self.nodesize}Bytes" + def contains(self, addr: int) -> bool: + pass -class MempoolProc: - def __init__(self, entry): - pool = utils.container_of(entry, mempool_s_type, "procfs") - blocksize = self.real_blocksize(pool) - ordblks = sq_count(pool["queue"]) - iordblks = sq_count(pool["iqueue"]) - aordblks = int(pool["nalloc"]) - narena = sq_count(pool["equeue"]) - name = str(entry["name"]) - if '"' in name: - # strip the name - name_split = name.split('"') - if len(name_split) == 3: - name = name_split[1] - self.pool = pool - self.name = name - self.arena = int( - narena * sizeof_sq_entry_t + (aordblks + ordblks + iordblks) * blocksize - ) - self.sizeblks = blocksize - self.ordblks = ordblks - self.iordblks = iordblks - self.aordblks = aordblks - if pool["wait"] and pool["expandsize"] == 0: - self.nwaiter = -int(self.pool["waitsem"]["semcount"]) - else: - self.nwaiter = 0 - - def real_blocksize(self, pool) -> int: - bsize = pool["blocksize"] - if CONFIG_MM_BACKTRACE > 0: - bsize = align_up(bsize + mempool_backtrace_type.sizeof, mempool_align()) - return int(bsize) - - def __str__(self) -> str: - return self.__class__.format( - self.name + ":", - self.arena, - self.sizeblks, - self.aordblks, - self.ordblks, - self.iordblks, - self.nwaiter, + def read_memory(self) -> memoryview: + return gdb.selected_inferior().read_memory(self.address, self.nodesize) + + +class MMLeak(gdb.Command): + """Dump memory manager heap""" + + def __init__(self): + self.elf = utils.import_check( + "elftools.elf.elffile", "ELFFile", "Please pip install pyelftools\n" ) + if not self.elf: + return - @staticmethod - def format(*args): - return "{:>13}{:>11}{:>9}{:>9}{:>9}{:>9}{:>9}".format(*args) + super().__init__("mm leak", gdb.COMMAND_USER) + utils.alias("memleak", "mm leak") - @staticmethod - def get_title(): - return MempoolProc.format( - "", "total", "bsize", "nused", "nfree", "nifree", "nwaiter" + def global_nodes(self) -> List[GlobalNode]: + cache = path.join( + path.dirname(path.abspath(gdb.objfiles()[0].filename)), + f"{utils.get_elf_md5()}-globals.json", ) + nodes: List[GlobalNode] = [] -class Mempool(gdb.Command): - def __init__(self): - super().__init__("mempool", gdb.COMMAND_USER) + if path.isfile(cache): + with open(cache, "r") as f: + variables = json.load(f) + for var in variables: + nodes.append(GlobalNode(var["address"], var["size"])) + return nodes - def parse(self) -> dict: - pools = {} - try: - entry = gdb.parse_and_eval("g_mempool_procfs") - except gdb.error: - return pools + longsize = utils.get_long_type().sizeof + for objfile in gdb.objfiles(): + elf = self.elf.load_from_path(objfile.filename) + symtab = elf.get_section_by_name(".symtab") + symbols = filter( + lambda s: s["st_info"]["type"] == "STT_OBJECT" + and s["st_size"] >= longsize, + symtab.iter_symbols(), + ) - while entry: - mempool = MempoolProc(entry) - key = int(entry.address) - if key in pools: - raise ValueError(f"mempool deadloop {pools}") - pools[key] = mempool - entry = entry["next"] + for symbol in symbols: + size = symbol["st_size"] // longsize * longsize + address = symbol["st_value"] + nodes.append(GlobalNode(address, size)) + + with open(cache, "w") as f: + variables = [ + {"address": node.address, "size": node.nodesize} for node in nodes + ] + str = utils.jsonify(variables) + f.write(str) + + return nodes + + def invoke(self, arg: str, from_tty: bool) -> None: + heaps = get_heaps("g_mmheap") + pids = [int(tcb["pid"]) for tcb in utils.get_tcbs()] + + def is_pid_alive(pid): + return pid in pids + + t = time.time() + print("Loading globals from elf...", flush=True, end="") + good_nodes = self.global_nodes() # Global memory are all good. + print(f" {time.time() - t:.2f}s", flush=True, end="\n") + + nodes_dict: Dict[int, MMNodeDump] = {} + sorted_addr = set() + t = time.time() + print("Gather memory nodes...", flush=True, end="") + for node in dump_nodes(heaps, used=True, no_pid=mm.PID_MM_MEMPOOL): + nodes_dict[node.address] = node + sorted_addr.add(node.address) + + sorted_addr = sorted(sorted_addr) + print(f" {time.time() - t:.2f}s", flush=True, end="\n") + + regions = [ + {"start": start.address, "end": end.address} + for heap in heaps + for start, end in heap.regions + ] + + longsize = utils.get_long_type().sizeof + + def pointers(node: MMNodeDump) -> Generator[int, None, None]: + # Return all possible pointers stored in this node + size = node.nodesize - node.overhead + memory = node.read_memory() + while size > 0: + size -= longsize + ptr = int.from_bytes(memory[size : size + longsize], "little") + if any(region["start"] <= ptr < region["end"] for region in regions): + yield ptr + + print("Leak analyzing...", flush=True, end="") + t = time.time() + for good in good_nodes: + for ptr in pointers(good): + if not (idx := bisect.bisect_right(sorted_addr, ptr)): + continue - return pools + node = nodes_dict[sorted_addr[idx - 1]] + if node.contains(ptr): + del sorted_addr[idx - 1] + good_nodes.append(node) - def invoke(self, args, from_tty): - pools = self.parse() - if len(pools) == 0: - gdb.write("mempool not found\n") - else: - gdb.write(f"{MempoolProc.get_title()}\n") - for pool in pools.values(): - gdb.write(f"{pool}\n") + print(f" {time.time() - t:.2f}s", flush=True, end="\n") + + leak_nodes = group_nodes(nodes_dict[addr] for addr in sorted_addr) + print_header() + total_blk = total_size = 0 + for node in leak_nodes.keys(): + count = len(leak_nodes[node]) + total_blk += count + total_size += count * node.nodesize + print_node(node, is_pid_alive(node.pid), count=len(leak_nodes[node])) + + print(f"Leaked {total_blk} blks, {total_size} bytes") diff --git a/tools/gdb/nuttxgdb/mm.py b/tools/gdb/nuttxgdb/mm.py new file mode 100644 index 00000000000..c1943bbc68f --- /dev/null +++ b/tools/gdb/nuttxgdb/mm.py @@ -0,0 +1,637 @@ +############################################################################ +# tools/gdb/nuttxgdb/mm.py +# +# Licensed to the Apache Software Foundation (ASF) under one or more +# contributor license agreements. See the NOTICE file distributed with +# this work for additional information regarding copyright ownership. The +# ASF licenses this file to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance with the +# License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# +############################################################################ + +from __future__ import annotations + +import argparse +from typing import Generator, List, Tuple + +import gdb + +from . import lists, utils +from .protocols import mm as p +from .utils import Value + +CONFIG_MM_BACKTRACE = utils.get_symbol_value("CONFIG_MM_BACKTRACE") +CONFIG_MM_BACKTRACE = -1 if CONFIG_MM_BACKTRACE is None else int(CONFIG_MM_BACKTRACE) + + +PID_MM_INVALID = -100 +PID_MM_MEMPOOL = -1 + + +class MemPoolBlock: + """ + Memory pool block instance. + """ + + MAGIC_ALLOC = 0x5555_5555 + + mempool_backtrace_s = utils.lookup_type("struct mempool_backtrace_s") + + def __init__(self, addr: int, blocksize: int, overhead: int) -> None: + """ + Initialize the memory pool block instance. + block: must be start address of the block, + blocksize: block size without backtrace overhead, + overhead: backtrace overhead size. + """ + self.overhead = overhead + self.from_pool = True + self.is_orphan = False + self.address = addr + self.blocksize = int(blocksize) + self.nodesize = int(blocksize) + self.overhead + # Lazy evaluation + self._backtrace = self._pid = self._seqno = self._magic = self._blk = None + + def __repr__(self) -> str: + return f"block@{hex(self.address)},size:{self.blocksize},seqno:{self.seqno},pid:{self.pid}" + + def __str__(self) -> str: + return self.__repr__() + + def __hash__(self) -> int: + return hash((self.pid, self.nodesize, self.backtrace)) + + def __eq__(self, value: MemPoolBlock) -> bool: + return ( + self.pid == value.pid + and self.nodesize == value.nodesize + and self.backtrace == value.backtrace + ) + + def contains(self, address: int) -> bool: + """Check if the address is in block's range, excluding overhead""" + return self.address <= address < self.address + self.blocksize + + @property + def blk(self) -> p.MemPoolBlock: + if not self._blk: + addr = int(self.address) + self.blocksize + self._blk = ( + gdb.Value(addr).cast(self.mempool_backtrace_s.pointer()).dereference() + ) + return self._blk + + @property + def is_free(self) -> bool: + if not self._magic: + self._magic = int(self.blk["magic"]) + + return CONFIG_MM_BACKTRACE and self._magic != self.MAGIC_ALLOC + + @property + def seqno(self) -> int: + if not self._seqno: + self._seqno = int(self.blk["seqno"]) if CONFIG_MM_BACKTRACE >= 0 else -100 + return self._seqno + + @property + def pid(self) -> int: + if not self._pid: + self._pid = ( + int(self.blk["pid"]) if CONFIG_MM_BACKTRACE >= 0 else PID_MM_INVALID + ) + return self._pid + + @property + def backtrace(self) -> Tuple[int]: + if CONFIG_MM_BACKTRACE <= 0: + return () + + if not self._backtrace: + self._backtrace = tuple( + int(self.blk["backtrace"][i]) for i in range(CONFIG_MM_BACKTRACE) + ) + return self._backtrace + + def read_memory(self) -> memoryview: + return gdb.selected_inferior().read_memory(self.address, self.blocksize) + + +class MemPool(Value, p.MemPool): + """ + Memory pool instance. + """ + + def __init__(self, mpool: Value, name=None) -> None: + if mpool.type.code == gdb.TYPE_CODE_PTR: + mpool = mpool.dereference() + super().__init__(mpool) + self._blksize = None + self._nfree = None + self._nifree = None + self._overhead = None + + def __repr__(self) -> str: + return f"{self.name}@{hex(self.address)},size:{self.size}/{self['blocksize']},nused:{self.nused},nfree:{self.nfree}" + + def __str__(self) -> str: + return self.__repr__() + + @property + def name(self) -> str: + try: + return self.procfs.name.string() + except Exception: + return "" + + @property + def memranges(self) -> Generator[Tuple[int, int], None, None]: + """Memory ranges of the pool""" + sq_entry_t = utils.lookup_type("sq_entry_t") + blksize = self.size + + if self.ibase: + blks = int(self.interruptsize) // blksize + base = int(self.ibase) + yield (base, base + blks * blksize) + + if not self.equeue.head: + return None + + # First queue has size of initialsize + ninit = int(self.initialsize) + ninit = ninit and (ninit - sq_entry_t.sizeof) // blksize + nexpand = (int(self.expandsize) - sq_entry_t.sizeof) // blksize + + for entry in lists.NxSQueue(self.equeue): + blks = ninit or nexpand + ninit = 0 + yield (int(entry) - blks * blksize, int(entry)) + + @property + def size(self) -> int: + """Real block size including backtrace overhead""" + if not self._blksize: + blksize = self["blocksize"] + backtrace = utils.get_symbol_value("CONFIG_MM_BACKTRACE") + if CONFIG_MM_BACKTRACE is not None and backtrace >= 0: + mempool_backtrace_s = utils.lookup_type("struct mempool_backtrace_s") + size_t = utils.lookup_type("size_t") + align = ( + utils.get_symbol_value("CONFIG_MM_DEFAULT_ALIGNMENT") + or 2 * size_t.sizeof + ) + blksize = blksize + mempool_backtrace_s.sizeof + blksize = (blksize + align - 1) & ~(align - 1) + self._blksize = int(blksize) + return self._blksize + + @property + def overhead(self) -> int: + if not self._overhead: + self._overhead = self.size - int(self["blocksize"]) + return self._overhead + + @property + def nwaiter(self) -> int: + return -int(self.waitsem.semcount) if self.wait and self.expandsize == 0 else 0 + + @property + def nused(self) -> int: + return int(self.nalloc) + + @property + def free(self) -> int: + return (self.nfree + self.nifree) * self.size + + @property + def nfree(self) -> int: + if not self._nfree: + self._nfree = lists.sq_count(self.queue) + return self._nfree + self.nifree + + @property + def nifree(self) -> int: + """Interrupt pool free blocks count""" + if not self._nifree: + self._nifree = lists.sq_count(self.iqueue) + return self._nifree + + @property + def total(self) -> int: + nqueue = lists.sq_count(self.equeue) + sq_entry_t = utils.lookup_type("sq_entry_t") + blocks = self.nused + self.nfree + return int(nqueue * sq_entry_t.sizeof + blocks * self.size) + + @property + def blks(self) -> Generator[MemPoolBlock, None, None]: + """Iterate over all blocks in the pool""" + sq_entry_t = utils.lookup_type("sq_entry_t") + blksize = self.size # Real block size including backtrace overhead + blocksize = self["blocksize"] + + def iterate(entry, nblocks): + base = int(entry) - nblocks * blksize + while nblocks > 0: + yield MemPoolBlock(base, blocksize, self.overhead) + base += blksize + nblocks -= 1 + + if self.ibase: + blks = int(self.interruptsize) // blksize + yield from iterate(self.ibase + blks * blksize, blks) + + if not self.equeue.head: + return None + + # First queue has size of initialsize + ninit = int(self.initialsize) + ninit = ninit and (ninit - sq_entry_t.sizeof) // blksize + nexpand = (int(self.expandsize) - sq_entry_t.sizeof) // blksize + + for entry in lists.NxSQueue(self.equeue): + yield from iterate(entry, ninit or nexpand) + ninit = 0 + + def contains(self, address: int) -> Tuple[bool, Value]: + ranges = self.memranges + if not ranges: + return False, None + + for start, end in ranges: + if start <= address < end: + return True, None + + def find(self, address: int) -> Value: + """Find the block that contains the given address""" + sq_entry_t = utils.lookup_type("sq_entry_t") + blksize = self.size + blocksize = self["blocksize"] + + def get_blk(base): + blkstart = base + (address - base) // blksize * blksize + return MemPoolBlock(blkstart, blocksize, self.overhead) + + if self.ibase: + # Check if it belongs to interrupt pool + blks = int(self.interruptsize) // blksize + base = int(self.ibase) + if base <= address < base + blks * blksize: + return get_blk(base) + + if not self.equeue.head: + return None + + # First queue has size of initialsize + ninit = int(self.initialsize) + ninit = ninit and (ninit - sq_entry_t.sizeof) // blksize + nexpand = (int(self.expandsize) - sq_entry_t.sizeof) // blksize + + for entry in lists.NxSQueue(self.equeue): + blks = ninit or nexpand + ninit = 0 + base = int(entry) - blks * blksize + if base <= address < int(entry): + return get_blk(base) + + def blks_free(self) -> Generator[MemPoolBlock, None, None]: + """Iterate over all free blocks in the pool""" + blocksize = self["blocksize"] + for entry in lists.NxSQueue(self.queue): + yield MemPoolBlock(int(entry), blocksize, self.overhead) + + def blks_used(self) -> Generator[MemPoolBlock, None, None]: + """Iterate over all used blocks in the pool""" + return filter(lambda blk: not blk.is_free, self.blks) + + +class MemPoolMultiple(Value, p.MemPoolMultiple): + """ + Multiple level memory pool instance. + """ + + def __init__(self, mpool: Value, name=None) -> None: + if mpool.type.code == gdb.TYPE_CODE_PTR: + mpool = mpool.dereference() + super().__init__(mpool) + + def __repr__(self) -> str: + return f"Multiple Level Memory Pool: {self.address}" + + def __str__(self) -> str: + return self.__repr__() + + @property + def pools(self) -> Generator[MemPool, None, None]: + for pool in utils.ArrayIterator(self["pools"], self.npools): + yield MemPool(pool) + + @property + def free(self) -> int: + return sum(pool.free for pool in self.pools) + + +class MMNode(gdb.Value, p.MMFreeNode): + """ + One memory node in the memory manager heap, either free or allocated. + The instance is always dereferenced to the actual node. + """ + + MM_ALLOC_BIT = 0x1 + MM_PREVFREE_BIT = 0x2 + MM_MASK_BIT = MM_ALLOC_BIT | MM_PREVFREE_BIT + MM_SIZEOF_ALLOCNODE = utils.sizeof("struct mm_allocnode_s") + MM_ALLOCNODE_OVERHEAD = MM_SIZEOF_ALLOCNODE - utils.sizeof("mmsize_t") + + def __init__(self, node: gdb.Value): + if node.type.code == gdb.TYPE_CODE_PTR: + node = node.dereference() + self._backtrace = None + self._address = None + self._nodesize = None + super().__init__(node) + + def __repr__(self): + return ( + f"{hex(self.address)}({'F' if self.is_free else 'A'}{'F' if self.is_prev_free else 'A'})" + f" size:{self.nodesize}/{self.prevsize if self.is_prev_free else '-'}" + f" seq:{self.seqno} pid:{self.pid} " + ) + + def __str__(self) -> str: + return self.__repr__() + + def __hash__(self) -> int: + return hash((self.pid, self.nodesize, self.backtrace)) + + def __eq__(self, value: MMNode) -> bool: + return ( + self.pid == value.pid + and self.nodesize == value.nodesize + and self.backtrace == value.backtrace + ) + + def contains(self, address): + """Check if the address is in node's range, excluding oeprhead""" + return ( + self.address + self.overhead + <= address + < self.address + self.nodesize - MMNode.MM_ALLOCNODE_OVERHEAD + ) + + def read_memory(self): + addr = int(self.address) + MMNode.MM_ALLOCNODE_OVERHEAD + size = self.nodesize - MMNode.MM_ALLOCNODE_OVERHEAD + return gdb.selected_inferior().read_memory(addr, size) + + @property + def address(self) -> int: + """Change 'void *' to int""" + if not self._address: + self._address = int(super().address) + return self._address + + @property + def prevsize(self) -> int: + """Size of preceding chunk size""" + return int(self["preceding"]) & ~MMNode.MM_MASK_BIT + + @property + def nodesize(self) -> int: + """Size of this chunk, including overhead""" + if not self._nodesize: + self._nodesize = int(self["size"]) & ~MMNode.MM_MASK_BIT + return self._nodesize + + @property + def usersize(self) -> int: + """Size of this chunk, excluding overhead""" + return self.nodesize - MMNode.MM_ALLOCNODE_OVERHEAD + + @property + def flink(self): + # Only free node has flink and blink + return self["flink"] if self.is_free else None + + @property + def blink(self): + # Only free node has flink and blink + return self["blink"] if self.is_free else None + + @property + def pid(self) -> int: + # Only available when CONFIG_MM_BACKTRACE >= 0 + if CONFIG_MM_BACKTRACE >= 0: + return int(self["pid"]) + return PID_MM_INVALID + + @property + def seqno(self) -> int: + return int(self["seqno"]) if CONFIG_MM_BACKTRACE >= 0 else -1 + + @property + def backtrace(self) -> List[Tuple[int, str, str]]: + if CONFIG_MM_BACKTRACE <= 0: + return () + + if not self._backtrace: + self._backtrace = tuple( + int(self["backtrace"][i]) for i in range(CONFIG_MM_BACKTRACE) + ) + return self._backtrace + + @property + def prevnode(self) -> MMNode: + addr = int(self.address) - self["presize"] + type = utils.lookup_type("struct mm_allocnode_s").pointer() + return MMNode(gdb.Value(addr).cast(type)) + + @property + def nextnode(self) -> MMNode: + addr = int(self.address) + self.nodesize + type = utils.lookup_type("struct mm_allocnode_s").pointer() + # Use gdb.Value for better performance + return MMNode(gdb.Value(addr).cast(type)) + + @property + def is_free(self) -> bool: + return not self["size"] & MMNode.MM_ALLOC_BIT + + @property + def is_prev_free(self) -> bool: + return self["preceding"] & MMNode.MM_PREVFREE_BIT + + @property + def is_orphan(self) -> bool: + # Report orphaned node and node likely to be orphaned(free-used-used-free) + return self.is_prev_free or self.nextnode.is_free + + @property + def from_pool(self) -> bool: + return False + + @property + def overhead(self) -> int: + return MMNode.MM_ALLOCNODE_OVERHEAD + + +class MMHeap(Value, p.MMHeap): + """ + One memory manager heap. It may contains multiple regions. + """ + + def __init__(self, heap: Value, name=None) -> None: + if heap.type.code == gdb.TYPE_CODE_PTR: + heap = heap.dereference() + super().__init__(heap) + + self.name = name or "" + + def __repr__(self) -> str: + return f"{self.name}@{self.address}, {self.nregions}regions, {int(self.heapsize) / 1024 :.1f}kB" + + def __str__(self) -> str: + return self.__repr__() + + @property + def curused(self) -> int: + return int(self.mm_curused) + + @property + def heapsize(self) -> int: + return int(self.mm_heapsize) + + @property + def free(self) -> int: + return self.heapsize - self.curused + + @property + def nregions(self) -> int: + return int(utils.get_field(self, "mm_nregions", default=1)) + + @property + def regions(self): + regions = self.nregions + for start, end in zip( + utils.ArrayIterator(self.mm_heapstart, regions), + utils.ArrayIterator(self.mm_heapend, regions), + ): + yield MMNode(start), MMNode(end) + + @property + def nodes(self) -> Generator[MMNode, None, None]: + for start, end in self.regions: + node = start + while node.address <= end.address: + yield node + node = node.nextnode + + def nodes_free(self) -> Generator[MMNode, None, None]: + return filter(lambda node: node.is_free, self.nodes) + + def nodes_used(self) -> Generator[MMNode, None, None]: + return filter(lambda node: not node.is_free, self.nodes) + + def contains(self, address: int) -> bool: + return any( + start.address <= address < end.address for start, end in self.regions + ) + + def find(self, address: int) -> MMNode: + for node in self.nodes: + if node.address <= address < node.address + node.nodesize: + return node + + +def get_heaps() -> List[MMHeap]: + # parse g_procfs_meminfo to get all heaps + heaps = [] + meminfo: p.ProcfsMeminfoEntry = utils.gdb_eval_or_none("g_procfs_meminfo") + if not meminfo and (heap := gdb.parse_and_eval("g_mmheap")): + heaps.append(MMHeap(heap)) + + while meminfo: + heaps.append(MMHeap(meminfo.heap, name=meminfo.name.string())) + meminfo = meminfo.next + + return heaps + + +def get_pools(heaps: List[Value] = []) -> Generator[MemPool, None, None]: + for heap in heaps or get_heaps(): + if not (mm_pool := heap.mm_mpool): + continue + + mpool = MemPoolMultiple(mm_pool) + for pool in mpool.pools: + yield pool + + +class MMHeapInfo(gdb.Command): + """Show basic heap information""" + + def __init__(self): + super().__init__("mm heap", gdb.COMMAND_USER) + + def invoke(self, arg: str, from_tty: bool) -> None: + for heap in get_heaps(): + regions = [(start.address, end.address) for start, end in heap.regions] + gdb.write(f"{heap} - has {len(list(heap.nodes))} nodes, regions:") + gdb.write(" ".join(f"{hex(start)}~{hex(end)}" for start, end in regions)) + gdb.write("\n") + + +class MMPoolInfo(gdb.Command): + """Show basic heap information""" + + def __init__(self): + super().__init__("mm pool", gdb.COMMAND_USER) + utils.alias("mempool", "mm pool") + + def invoke(self, arg: str, from_tty: bool) -> None: + parser = argparse.ArgumentParser(description="Dump memory pool information.") + parser.add_argument( + "--heap", type=str, help="Which heap's pool to show", default=None + ) + + try: + args = parser.parse_args(gdb.string_to_argv(arg)) + except SystemExit: + return + + heaps = [gdb.parse_and_eval(args.heap)] if args.heap else get_heaps() + if not (pools := list(get_pools(heaps))): + gdb.write("No pools found.\n") + return + + count = len(pools) + gdb.write(f"Total {count} pools\n") + + name_max = max(len(pool.name) for pool in pools) + 11 # 11: "@0x12345678" + formatter = "{:>%d} {:>11} {:>9} {:>9} {:>9} {:>9} {:>9}\n" % name_max + head = ("", "total", "bsize", "nused", "nfree", "nifree", "nwaiter") + + gdb.write(formatter.format(*head)) + for pool in pools: + gdb.write( + formatter.format( + f"{pool.name}@{pool.address:#x}", + pool.total, + pool.size, + pool.nused, + pool.nfree, + pool.nifree, + pool.nwaiter, + ) + ) diff --git a/tools/gdb/nuttxgdb/prefix.py b/tools/gdb/nuttxgdb/prefix.py index b5255cc3e0d..08214b1b256 100644 --- a/tools/gdb/nuttxgdb/prefix.py +++ b/tools/gdb/nuttxgdb/prefix.py @@ -26,3 +26,10 @@ class ForeachPrefix(gdb.Command): def __init__(self): super(ForeachPrefix, self).__init__("foreach", gdb.COMMAND_USER, prefix=True) + + +class MMPrefixCommand(gdb.Command): + """Memory manager related commands prefix.""" + + def __init__(self): + super().__init__("mm", gdb.COMMAND_USER, prefix=True) diff --git a/tools/gdb/nuttxgdb/protocols/mm.py b/tools/gdb/nuttxgdb/protocols/mm.py new file mode 100644 index 00000000000..e869119b85f --- /dev/null +++ b/tools/gdb/nuttxgdb/protocols/mm.py @@ -0,0 +1,120 @@ +############################################################################ +# tools/gdb/nuttxgdb/protocols/fs.py +# +# Licensed to the Apache Software Foundation (ASF) under one or more +# contributor license agreements. See the NOTICE file distributed with +# this work for additional information regarding copyright ownership. The +# ASF licenses this file to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance with the +# License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# +############################################################################ + +from __future__ import annotations + +from typing import List + +from .value import Value + + +class ProcfsMeminfoEntry(Value): + """struct procfs_meminfo_entry_s""" + + name: Value + heap: Value + next: ProcfsMeminfoEntry + + +class MMAllocNode(Value): + """struct mm_allocnode_s""" + + preceding: Value + size: Value + pid: Value + seqno: Value + backtrace: Value + + +class MMFreeNode(Value): + """struct mm_freenode_s""" + + preceding: Value + size: Value + pid: Value + seqno: Value + backtrace: Value + flink: MMFreeNode + blink: MMFreeNode + + +class MMHeap(Value): + """struct mm_heap_s""" + + mm_lock: Value + mm_heapsize: Value + mm_maxused: Value + mm_curused: Value + mm_heapstart: List[MMAllocNode] + mm_heapend: List[MMAllocNode] + mm_nregions: Value + mm_nodelist: Value + + +class MemPool(Value): + """struct mempool_s""" + + initialsize: Value + interruptsize: Value + expandsize: Value + wait: Value + priv: Value + alloc: Value + free: Value + check: Value + ibase: Value + queue: Value + iqueue: Value + equeue: Value + nalloc: Value + lock: Value + waitsem: Value + procfs: Value + + +class MemPoolMultiple(Value): + """struct mempool_multiple_s""" + + pools: List[MemPool] + npools: Value + expandsize: Value + minpoolsize: Value + arg: Value + alloc: Value + alloc_size: Value + free: Value + alloced: Value + delta: Value + lock: Value + chunk_queue: Value + chunk_size: Value + dict_used: Value + dict_col_num_log2: Value + dict_row_num: Value + dict: Value + + +class MemPoolBlock(Value): + """struct mempool_backtrace_s""" + + magic: Value + pid: Value + seqno: Value + backtrace: Value diff --git a/tools/gdb/nuttxgdb/utils.py b/tools/gdb/nuttxgdb/utils.py index 56d2d416124..80ef920ad4d 100644 --- a/tools/gdb/nuttxgdb/utils.py +++ b/tools/gdb/nuttxgdb/utils.py @@ -498,6 +498,13 @@ def parse_arg(arg: str) -> Union[gdb.Value, int]: return None +def alias(name, command): + try: + gdb.execute(f"alias {name} = {command}") + except gdb.error: + pass + + def nitems(array): array_type = array.type element_type = array_type.target() diff --git a/tools/gdb/tests/test_runtime_memory.py b/tools/gdb/tests/test_runtime_memory.py index 48953b71687..fac648647e0 100644 --- a/tools/gdb/tests/test_runtime_memory.py +++ b/tools/gdb/tests/test_runtime_memory.py @@ -18,6 +18,7 @@ # ############################################################################ +import re import unittest import gdb @@ -31,9 +32,9 @@ class TestMemory(unittest.TestCase): def setUpClass(cls): pass - def check_output(self, out, expect="Total Blks Total Size"): - if expect not in out: - self.fail(f"Got: {out}") + def check_output(self, out, expect=r"Total \d+ blks, \d+ bytes"): + if not re.compile(expect).search(out): + self.fail(f"Got: \n{out}") def test_memdump(self): out = gdb.execute("memdump", to_string=True) @@ -46,15 +47,15 @@ class TestMemory(unittest.TestCase): def test_memdump_addr(self): heap_start = gdb.parse_and_eval("g_mmheap")["mm_heapstart"][0] out = gdb.execute(f"memdump -a {hex(heap_start)}", to_string=True) - self.check_output(out, expect="found belongs to") + self.check_output(out, expect=r"found belongs to") - def test_memdump_used(self): - out = gdb.execute("memdump --used", to_string=True) + def test_memdump_free(self): + out = gdb.execute("memdump --free", to_string=True) self.check_output(out) def test_memleak(self): out = gdb.execute("memleak", to_string=True) - self.check_output(out, expect="total leak memory is") + self.check_output(out, expect=r"Leaked \d+ blks, \d+ bytes") # memmap may stuck because of huge 2GB memory qemu provides. # def test_memmap(self): @@ -62,10 +63,13 @@ class TestMemory(unittest.TestCase): def test_memfrag(self): out = gdb.execute("memfrag", to_string=True) - self.check_output(out, expect="memory fragmentation rate") + self.check_output(out, expect=r"fragmentation rate") def test_mempool(self): out = gdb.execute("mempool", to_string=True) - self.check_output( - out, expect="total bsize nused nfree nifree nwaiter" - ) + self.check_output(out, expect=r"Total \d+ pools") + + def test_mm_heap(self): + out = gdb.execute("mm heap", to_string=True) + # Umem@0x41977b78, 1regions, 94304.1kB - has 1408 nodes, regions:0x41977f78~0x4758ffd0 + self.check_output(out, expect=r"Umem@0x[0-9a-f]+, \d+regions, \d+\.\d+kB") -- Gitee From 4d4ffa1e58ac1fa83dcf7c5b45b9ad1e2fc109d4 Mon Sep 17 00:00:00 2001 From: xuxingliang Date: Mon, 11 Nov 2024 17:55:24 +0800 Subject: [PATCH 005/235] gdb/mm: move memleak to standalone file VELAPLATFO-46132 Change-Id: I787df863ba2da3f4024279ef86c0d4bc08ec4e11 Signed-off-by: xuxingliang --- tools/gdb/nuttxgdb/memdump.py | 142 -------------------------------- tools/gdb/nuttxgdb/memleak.py | 148 ++++++++++++++++++++++++++++++++++ 2 files changed, 148 insertions(+), 142 deletions(-) create mode 100644 tools/gdb/nuttxgdb/memleak.py diff --git a/tools/gdb/nuttxgdb/memdump.py b/tools/gdb/nuttxgdb/memdump.py index 8652fa4f833..487589831ac 100644 --- a/tools/gdb/nuttxgdb/memdump.py +++ b/tools/gdb/nuttxgdb/memdump.py @@ -19,11 +19,7 @@ ############################################################################ import argparse -import bisect -import json -import time from collections import defaultdict -from os import path from typing import Dict, Generator, List, Protocol, Tuple import gdb @@ -419,141 +415,3 @@ class MMMap(gdb.Command): output = args.output or f"{name}.png" self.save_memory_map(heap.nodes_used(), output) gdb.write(f"Memory map saved to {output}\n") - - -class GlobalNode(MMNodeDump): - def __init__(self, address: int, nodesize: int): - self.address = address - self.nodesize = nodesize - self.pid = None - self.seqno = None - self.overhead = 0 - self.backtrace = () - - def __repr__(self): - return f"GlobalVar@{self.address:x}:{self.nodesize}Bytes" - - def contains(self, addr: int) -> bool: - pass - - def read_memory(self) -> memoryview: - return gdb.selected_inferior().read_memory(self.address, self.nodesize) - - -class MMLeak(gdb.Command): - """Dump memory manager heap""" - - def __init__(self): - self.elf = utils.import_check( - "elftools.elf.elffile", "ELFFile", "Please pip install pyelftools\n" - ) - if not self.elf: - return - - super().__init__("mm leak", gdb.COMMAND_USER) - utils.alias("memleak", "mm leak") - - def global_nodes(self) -> List[GlobalNode]: - cache = path.join( - path.dirname(path.abspath(gdb.objfiles()[0].filename)), - f"{utils.get_elf_md5()}-globals.json", - ) - - nodes: List[GlobalNode] = [] - - if path.isfile(cache): - with open(cache, "r") as f: - variables = json.load(f) - for var in variables: - nodes.append(GlobalNode(var["address"], var["size"])) - return nodes - - longsize = utils.get_long_type().sizeof - for objfile in gdb.objfiles(): - elf = self.elf.load_from_path(objfile.filename) - symtab = elf.get_section_by_name(".symtab") - symbols = filter( - lambda s: s["st_info"]["type"] == "STT_OBJECT" - and s["st_size"] >= longsize, - symtab.iter_symbols(), - ) - - for symbol in symbols: - size = symbol["st_size"] // longsize * longsize - address = symbol["st_value"] - nodes.append(GlobalNode(address, size)) - - with open(cache, "w") as f: - variables = [ - {"address": node.address, "size": node.nodesize} for node in nodes - ] - str = utils.jsonify(variables) - f.write(str) - - return nodes - - def invoke(self, arg: str, from_tty: bool) -> None: - heaps = get_heaps("g_mmheap") - pids = [int(tcb["pid"]) for tcb in utils.get_tcbs()] - - def is_pid_alive(pid): - return pid in pids - - t = time.time() - print("Loading globals from elf...", flush=True, end="") - good_nodes = self.global_nodes() # Global memory are all good. - print(f" {time.time() - t:.2f}s", flush=True, end="\n") - - nodes_dict: Dict[int, MMNodeDump] = {} - sorted_addr = set() - t = time.time() - print("Gather memory nodes...", flush=True, end="") - for node in dump_nodes(heaps, used=True, no_pid=mm.PID_MM_MEMPOOL): - nodes_dict[node.address] = node - sorted_addr.add(node.address) - - sorted_addr = sorted(sorted_addr) - print(f" {time.time() - t:.2f}s", flush=True, end="\n") - - regions = [ - {"start": start.address, "end": end.address} - for heap in heaps - for start, end in heap.regions - ] - - longsize = utils.get_long_type().sizeof - - def pointers(node: MMNodeDump) -> Generator[int, None, None]: - # Return all possible pointers stored in this node - size = node.nodesize - node.overhead - memory = node.read_memory() - while size > 0: - size -= longsize - ptr = int.from_bytes(memory[size : size + longsize], "little") - if any(region["start"] <= ptr < region["end"] for region in regions): - yield ptr - - print("Leak analyzing...", flush=True, end="") - t = time.time() - for good in good_nodes: - for ptr in pointers(good): - if not (idx := bisect.bisect_right(sorted_addr, ptr)): - continue - - node = nodes_dict[sorted_addr[idx - 1]] - if node.contains(ptr): - del sorted_addr[idx - 1] - good_nodes.append(node) - - print(f" {time.time() - t:.2f}s", flush=True, end="\n") - - leak_nodes = group_nodes(nodes_dict[addr] for addr in sorted_addr) - print_header() - total_blk = total_size = 0 - for node in leak_nodes.keys(): - count = len(leak_nodes[node]) - total_blk += count - total_size += count * node.nodesize - print_node(node, is_pid_alive(node.pid), count=len(leak_nodes[node])) - - print(f"Leaked {total_blk} blks, {total_size} bytes") diff --git a/tools/gdb/nuttxgdb/memleak.py b/tools/gdb/nuttxgdb/memleak.py new file mode 100644 index 00000000000..482d1d55d3d --- /dev/null +++ b/tools/gdb/nuttxgdb/memleak.py @@ -0,0 +1,148 @@ +############################################################################ +# tools/gdb/nuttxgdb/memleak.py +# +# Licensed to the Apache Software Foundation (ASF) under one or more +# contributor license agreements. See the NOTICE file distributed with +# this work for additional information regarding copyright ownership. The +# ASF licenses this file to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance with the +# License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# +############################################################################ + +import bisect +import time +from typing import Dict, Generator, List + +import gdb + +from . import memdump, mm, utils + + +class GlobalNode(memdump.MMNodeDump): + def __init__(self, address: int, nodesize: int): + self.address = address + self.nodesize = nodesize + self.pid = None + self.seqno = None + self.overhead = 0 + self.backtrace = () + + def __repr__(self): + return f"GlobalVar@{self.address:x}:{self.nodesize}Bytes" + + def contains(self, addr: int) -> bool: + pass + + def read_memory(self) -> memoryview: + return gdb.selected_inferior().read_memory(self.address, self.nodesize) + + +class MMLeak(gdb.Command): + """Dump memory manager heap""" + + def __init__(self): + self.elf = utils.import_check( + "elftools.elf.elffile", "ELFFile", "Please pip install pyelftools\n" + ) + if not self.elf: + return + + super().__init__("mm leak", gdb.COMMAND_USER) + utils.alias("memleak", "mm leak") + + def global_nodes(self) -> List[GlobalNode]: + nodes: List[GlobalNode] = [] + + longsize = utils.get_long_type().sizeof + for objfile in gdb.objfiles(): + elf = self.elf.load_from_path(objfile.filename) + symtab = elf.get_section_by_name(".symtab") + symbols = filter( + lambda s: s["st_info"]["type"] == "STT_OBJECT" + and s["st_size"] >= longsize, + symtab.iter_symbols(), + ) + + for symbol in symbols: + size = symbol["st_size"] // longsize * longsize + address = symbol["st_value"] + nodes.append(GlobalNode(address, size)) + + return nodes + + def invoke(self, arg: str, from_tty: bool) -> None: + heaps = memdump.get_heaps("g_mmheap") + pids = [int(tcb["pid"]) for tcb in utils.get_tcbs()] + + def is_pid_alive(pid): + return pid in pids + + t = time.time() + print("Loading globals from elf...", flush=True, end="") + good_nodes = self.global_nodes() # Global memory are all good. + print(f" {time.time() - t:.2f}s", flush=True, end="\n") + + nodes_dict: Dict[int, memdump.MMNodeDump] = {} + sorted_addr = set() + t = time.time() + print("Gather memory nodes...", flush=True, end="") + for node in memdump.dump_nodes(heaps, used=True, no_pid=mm.PID_MM_MEMPOOL): + nodes_dict[node.address] = node + sorted_addr.add(node.address) + + sorted_addr = sorted(sorted_addr) + print(f" {time.time() - t:.2f}s", flush=True, end="\n") + + regions = [ + {"start": start.address, "end": end.address} + for heap in heaps + for start, end in heap.regions + ] + + longsize = utils.get_long_type().sizeof + + def pointers(node: memdump.MMNodeDump) -> Generator[int, None, None]: + # Return all possible pointers stored in this node + size = node.nodesize - node.overhead + memory = node.read_memory() + while size > 0: + size -= longsize + ptr = int.from_bytes(memory[size : size + longsize], "little") + if any(region["start"] <= ptr < region["end"] for region in regions): + yield ptr + + print("Leak analyzing...", flush=True, end="") + t = time.time() + for good in good_nodes: + for ptr in pointers(good): + if not (idx := bisect.bisect_right(sorted_addr, ptr)): + continue + + node = nodes_dict[sorted_addr[idx - 1]] + if node.contains(ptr): + del sorted_addr[idx - 1] + good_nodes.append(node) + + print(f" {time.time() - t:.2f}s", flush=True, end="\n") + + leak_nodes = memdump.group_nodes(nodes_dict[addr] for addr in sorted_addr) + memdump.print_header() + total_blk = total_size = 0 + for node in leak_nodes.keys(): + count = len(leak_nodes[node]) + total_blk += count + total_size += count * node.nodesize + memdump.print_node( + node, is_pid_alive(node.pid), count=len(leak_nodes[node]) + ) + + print(f"Leaked {total_blk} blks, {total_size} bytes") -- Gitee From dada1d6127e21b378c67502dbe23f8117f07acd6 Mon Sep 17 00:00:00 2001 From: xuxingliang Date: Mon, 11 Nov 2024 17:37:31 +0800 Subject: [PATCH 006/235] gdb/mm: cache global variables to save time of memleak check VELAPLATFO-46132 Change-Id: Ia8dbc5b70c7e7312c332a7cd308a2d6f705d8487 Signed-off-by: xuxingliang --- tools/gdb/nuttxgdb/memleak.py | 21 +++++++++++++++++++++ tools/gdb/nuttxgdb/utils.py | 9 +++++++++ 2 files changed, 30 insertions(+) diff --git a/tools/gdb/nuttxgdb/memleak.py b/tools/gdb/nuttxgdb/memleak.py index 482d1d55d3d..431f4b9c5cc 100644 --- a/tools/gdb/nuttxgdb/memleak.py +++ b/tools/gdb/nuttxgdb/memleak.py @@ -19,7 +19,9 @@ ############################################################################ import bisect +import json import time +from os import path from typing import Dict, Generator, List import gdb @@ -60,8 +62,20 @@ class MMLeak(gdb.Command): utils.alias("memleak", "mm leak") def global_nodes(self) -> List[GlobalNode]: + cache = path.join( + path.dirname(path.abspath(gdb.objfiles()[0].filename)), + f"{utils.get_elf_md5()}-globals.json", + ) + nodes: List[GlobalNode] = [] + if path.isfile(cache): + with open(cache, "r") as f: + variables = json.load(f) + for var in variables: + nodes.append(GlobalNode(var["address"], var["size"])) + return nodes + longsize = utils.get_long_type().sizeof for objfile in gdb.objfiles(): elf = self.elf.load_from_path(objfile.filename) @@ -77,6 +91,13 @@ class MMLeak(gdb.Command): address = symbol["st_value"] nodes.append(GlobalNode(address, size)) + with open(cache, "w") as f: + variables = [ + {"address": node.address, "size": node.nodesize} for node in nodes + ] + str = utils.jsonify(variables) + f.write(str) + return nodes def invoke(self, arg: str, from_tty: bool) -> None: diff --git a/tools/gdb/nuttxgdb/utils.py b/tools/gdb/nuttxgdb/utils.py index 80ef920ad4d..fe3f0365a95 100644 --- a/tools/gdb/nuttxgdb/utils.py +++ b/tools/gdb/nuttxgdb/utils.py @@ -21,6 +21,7 @@ from __future__ import annotations import argparse +import hashlib import importlib import json import os @@ -854,6 +855,14 @@ def gather_gdbcommands(modules=None, path=None) -> List[gdb.Command]: return commands +def get_elf_md5(): + """Return the md5 checksum of the current ELF file""" + file = gdb.objfiles()[0].filename + with open(file, "rb") as f: + hash = hashlib.md5(f.read()).hexdigest() + return hash + + def jsonify(obj, indent=None): if not obj: return "{}" -- Gitee From 6e24e87a60dd83c5bea46f85780a00bc8900416d Mon Sep 17 00:00:00 2001 From: xuxingliang Date: Wed, 13 Nov 2024 16:10:24 +0800 Subject: [PATCH 007/235] gdb/memdump: show prev and next node in address finding mode VELAPLATFO-47060 This will make it easier to debug memory corruption when agacent node is corrupted. Change-Id: I0b79d8b052d6c7a3a8988ac611020fb5d93919ac Signed-off-by: xuxingliang --- tools/gdb/nuttxgdb/memdump.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/tools/gdb/nuttxgdb/memdump.py b/tools/gdb/nuttxgdb/memdump.py index 487589831ac..7d454522eea 100644 --- a/tools/gdb/nuttxgdb/memdump.py +++ b/tools/gdb/nuttxgdb/memdump.py @@ -238,7 +238,11 @@ class MMDump(gdb.Command): if node or (node := self.find(heaps, addr)): printnode(node, 1) source = "Pool" if node.from_pool else "Heap" - print(f"{addr: #x} found belongs to {source}, node@{node.address:#x}") + print(f"{addr: #x} found belongs to {source} {node}") + if node.prevnode: + print(f"prevnode: {node.prevnode}") + if node.nextnode: + print(f"nextnode: {node.nextnode}") else: print(f"Address {addr:#x} not found in any heap") return -- Gitee From f9f140b52ba5664100202f73571007042e2b0717 Mon Sep 17 00:00:00 2001 From: xuxingliang Date: Wed, 13 Nov 2024 16:13:32 +0800 Subject: [PATCH 008/235] gdb/mm: fix prev free judging and region search VELAPLATFO-47060 1. The prev free flag should use field size instead of preceding to compare. 2. If not prev-free, then prevnode should be None. 3. Cast type to mm_freenode_s in order to access flink, blink when node is free. 4. Heap itself is also included in first region. Change-Id: I1e41ac40349ee52a89126929452688cdd59ff6ee Signed-off-by: xuxingliang --- tools/gdb/nuttxgdb/mm.py | 47 +++++++++++++++++--------- tools/gdb/tests/test_runtime_memory.py | 5 +-- 2 files changed, 34 insertions(+), 18 deletions(-) diff --git a/tools/gdb/nuttxgdb/mm.py b/tools/gdb/nuttxgdb/mm.py index c1943bbc68f..7ff7164967b 100644 --- a/tools/gdb/nuttxgdb/mm.py +++ b/tools/gdb/nuttxgdb/mm.py @@ -353,6 +353,7 @@ class MMNode(gdb.Value, p.MMFreeNode): MM_MASK_BIT = MM_ALLOC_BIT | MM_PREVFREE_BIT MM_SIZEOF_ALLOCNODE = utils.sizeof("struct mm_allocnode_s") MM_ALLOCNODE_OVERHEAD = MM_SIZEOF_ALLOCNODE - utils.sizeof("mmsize_t") + MM_MIN_CHUNK = utils.get_symbol_value("MM_MIN_CHUNK", locspec="mm_initialize") def __init__(self, node: gdb.Value): if node.type.code == gdb.TYPE_CODE_PTR: @@ -422,12 +423,12 @@ class MMNode(gdb.Value, p.MMFreeNode): @property def flink(self): # Only free node has flink and blink - return self["flink"] if self.is_free else None + return MMNode(self["flink"]) if self.is_free and self["flink"] else None @property def blink(self): # Only free node has flink and blink - return self["blink"] if self.is_free else None + return MMNode(self["blink"]) if self.is_free and self["blink"] else None @property def pid(self) -> int: @@ -453,14 +454,17 @@ class MMNode(gdb.Value, p.MMFreeNode): @property def prevnode(self) -> MMNode: - addr = int(self.address) - self["presize"] - type = utils.lookup_type("struct mm_allocnode_s").pointer() + if not self.is_prev_free: + return None + + addr = int(self.address) - self.prevsize + type = utils.lookup_type("struct mm_freenode_s").pointer() return MMNode(gdb.Value(addr).cast(type)) @property def nextnode(self) -> MMNode: addr = int(self.address) + self.nodesize - type = utils.lookup_type("struct mm_allocnode_s").pointer() + type = utils.lookup_type("struct mm_freenode_s").pointer() # Use gdb.Value for better performance return MMNode(gdb.Value(addr).cast(type)) @@ -470,7 +474,7 @@ class MMNode(gdb.Value, p.MMFreeNode): @property def is_prev_free(self) -> bool: - return self["preceding"] & MMNode.MM_PREVFREE_BIT + return self["size"] & MMNode.MM_PREVFREE_BIT @property def is_orphan(self) -> bool: @@ -497,9 +501,13 @@ class MMHeap(Value, p.MMHeap): super().__init__(heap) self.name = name or "" + self._regions = None def __repr__(self) -> str: - return f"{self.name}@{self.address}, {self.nregions}regions, {int(self.heapsize) / 1024 :.1f}kB" + regions = [ + f"{hex(start.address)}~{hex(end.address)}" for start, end in self.regions + ] + return f"{self.name}@{self.address}, {int(self.heapsize) / 1024 :.1f}kB {self.nregions}regions: {','.join(regions)}" def __str__(self) -> str: return self.__repr__() @@ -520,14 +528,21 @@ class MMHeap(Value, p.MMHeap): def nregions(self) -> int: return int(utils.get_field(self, "mm_nregions", default=1)) + @property + def mm_mpool(self) -> Value: + return utils.get_field(self, "mm_mpool", default=None) + @property def regions(self): - regions = self.nregions - for start, end in zip( - utils.ArrayIterator(self.mm_heapstart, regions), - utils.ArrayIterator(self.mm_heapend, regions), - ): - yield MMNode(start), MMNode(end) + if not self._regions: + regions = self.nregions + self._regions = [] + for start, end in zip( + utils.ArrayIterator(self.mm_heapstart, regions), + utils.ArrayIterator(self.mm_heapend, regions), + ): + self._regions.append((MMNode(start), MMNode(end))) + return self._regions @property def nodes(self) -> Generator[MMNode, None, None]: @@ -544,9 +559,9 @@ class MMHeap(Value, p.MMHeap): return filter(lambda node: not node.is_free, self.nodes) def contains(self, address: int) -> bool: - return any( - start.address <= address < end.address for start, end in self.regions - ) + ranges = [[int(start.address), int(end.address)] for start, end in self.regions] + ranges[0][0] = int(self.address) # The heap itself is also in the range + return any(start <= address <= end for start, end in ranges) def find(self, address: int) -> MMNode: for node in self.nodes: diff --git a/tools/gdb/tests/test_runtime_memory.py b/tools/gdb/tests/test_runtime_memory.py index fac648647e0..69b5e550a73 100644 --- a/tools/gdb/tests/test_runtime_memory.py +++ b/tools/gdb/tests/test_runtime_memory.py @@ -71,5 +71,6 @@ class TestMemory(unittest.TestCase): def test_mm_heap(self): out = gdb.execute("mm heap", to_string=True) - # Umem@0x41977b78, 1regions, 94304.1kB - has 1408 nodes, regions:0x41977f78~0x4758ffd0 - self.check_output(out, expect=r"Umem@0x[0-9a-f]+, \d+regions, \d+\.\d+kB") + # Umem@0x21023230, 2101106.4kB 2regions: 0x21023638~0x213fffd0,0x60000000~0xdfffffd0 + # - has 21 nodes, regions:0x21023638~0x213fffd0 0x60000000~0xdfffffd0 + self.check_output(out, expect=r"Umem@0x[0-9a-f]+, \d+\.\d+kB \d+regions") -- Gitee From 505641412c21239e1391223a45c970a7a1580928 Mon Sep 17 00:00:00 2001 From: xuxingliang Date: Wed, 13 Nov 2024 16:09:03 +0800 Subject: [PATCH 009/235] gdb: add tool to check heap memory corruption VELAPLATFO-47060 Only heap nodes are checked for now. Change-Id: Ie33c38094decc5b576b718f53448a1a121e7d42a Signed-off-by: xuxingliang --- tools/gdb/nuttxgdb/memcheck.py | 173 +++++++++++++++++++++++++++++++++ 1 file changed, 173 insertions(+) create mode 100644 tools/gdb/nuttxgdb/memcheck.py diff --git a/tools/gdb/nuttxgdb/memcheck.py b/tools/gdb/nuttxgdb/memcheck.py new file mode 100644 index 00000000000..8f91c002aad --- /dev/null +++ b/tools/gdb/nuttxgdb/memcheck.py @@ -0,0 +1,173 @@ +############################################################################ +# tools/gdb/nuttxgdb/memcheck.py +# +# Licensed to the Apache Software Foundation (ASF) under one or more +# contributor license agreements. See the NOTICE file distributed with +# this work for additional information regarding copyright ownership. The +# ASF licenses this file to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance with the +# License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# +############################################################################ + +import traceback +from collections import defaultdict +from typing import Dict, List, Tuple + +import gdb + +from . import memdump, mm, utils + + +class MMCheck(gdb.Command): + """Check memory manager and pool integrity""" + + def __init__(self): + super().__init__("mm check", gdb.COMMAND_USER) + utils.alias("memcheck", "mm check") + + def check_heap(self, heap: mm.MMHeap) -> Dict[int, List[str]]: # noqa: C901 + """Check heap integrity and return list of issues in string""" + issues = defaultdict(list) # key: address, value: list of issues + + def report(e, heap, node: mm.MMNode) -> None: + gdb.write(f"Error happened during heap check: {e}\n") + try: + gdb.write(f" heap: {heap}\n") + gdb.write(f"current node: {node}") + if node.prevnode: + gdb.write(f" prev node: {node.prevnode}") + if node.nextnode: + gdb.write(f" next node: {node.nextnode}") + + gdb.write("\n") + except gdb.error as e: + gdb.write(f"Error happened during report: {e}\n") + + def is_node_corrupted(node: mm.MMNode) -> Tuple[bool, str]: + # Must be in this heap + if not heap.contains(node.address): + return True, f"node@{hex(node.address)} not in heap" + + # Check next node + if node.nodesize > node.MM_SIZEOF_ALLOCNODE: + nextnode = node.nextnode + if not heap.contains(nextnode.address): + return True, f"nexnode@{hex(nextnode.address)} not in heap" + if node.is_free: + if not nextnode.is_prev_free: + # This node is free, then next node must have prev free set + return ( + True, + f"nextnode@{hex(nextnode.address)} not marked as prev free", + ) + + if nextnode.prevsize != node.nodesize: + return ( + True, + f"nextnode @{hex(nextnode.address)} prevsize not match", + ) + + if node.is_free: + if node.nodesize < node.MM_MIN_CHUNK: + return True, f"nodesize {int(node.nodesize)} too small" + + if node.flink and node.flink.blink != node: + return ( + True, + f"flink not intact: {hex(node.flink.blink)}, node: {hex(node.address)}", + ) + + if node.blink.flink != node: + return ( + True, + f"blink not intact: {hex(node.blink.flink)}, node: {hex(node.address)}", + ) + + # Node should be in correctly sorted order + if (blinksize := mm.MMNode(node.blink).nodesize) > node.nodesize: + return ( + True, + f"blink node not in sorted order: {blinksize} > {node.nodesize}", + ) + + fnode = mm.MMNode(node.flink) if node.flink else None + if fnode and fnode.nodesize and fnode.nodesize < node.nodesize: + return ( + True, + f"flink node not in sorted order: {fnode.nodesize} < {node.nodesize}", + ) + else: + # Node is allocated. + if node.nodesize < node.MM_SIZEOF_ALLOCNODE: + return True, f"nodesize {node.nodesize} too small" + + return False, "" + + try: + # Check nodes in physical memory order + for node in heap.nodes: + corrupted, reason = is_node_corrupted(node) + if corrupted: + issues[node.address].append(reason) + + # Check free list + for node in utils.ArrayIterator(heap.mm_nodelist): + # node is in type of gdb.Value, struct mm_freenode_s + while node: + address = int(node.address) + if node["flink"] and not heap.contains(node["flink"]): + issues[address].append( + f"flink {hex(node['flink'])} not in heap" + ) + break + + if address in issues or node["size"] == 0: + # This node is already checked or size is 0, which is a node in node table + node = node["flink"] + continue + + # Check if this node is corrupted + corrupted, reason = is_node_corrupted(mm.MMNode(node)) + if corrupted: + issues[address].append(reason) + break + + # Continue to it's flink + node = node["flink"] + + except Exception as e: + report(e, heap, node) + traceback.print_exc() + + return issues + + def dump_issues(self, heap, issues: Dict[int, List[str]]) -> None: + for address, reasons in issues.items(): + gdb.write( + f"{len(reasons)} issues @{hex(address)}: " f"{','.join(reasons)}\n" + ) + + def invoke(self, arg: str, from_tty: bool) -> None: + try: + heaps = memdump.get_heaps() + for heap in heaps: + issues = self.check_heap(heap) + if not issues: + continue + + print(f"Found {len(issues)} issues in heap {heap}") + self.dump_issues(heap, issues) + except Exception as e: + print(f"Error happened during check: {e}") + traceback.print_exc() + + print("Check done.") -- Gitee From 230873b2c918f30201ee410380b851403ecf6d9d Mon Sep 17 00:00:00 2001 From: xuxingliang Date: Fri, 15 Nov 2024 10:43:44 +0800 Subject: [PATCH 010/235] mm: dump node overheadp during memdump VELAPLATFO-47060 Change-Id: I7f91459df20216f01cf92aeb1689f41721f864ac Signed-off-by: xuxingliang --- mm/mempool/mempool.c | 15 ++++++----- mm/mm_heap/mm_memdump.c | 26 +++++++++++-------- tools/gdb/nuttxgdb/memdump.py | 23 ++++++++++++++--- tools/gdb/nuttxgdb/mm.py | 18 ++++++++++++-- tools/parsememdump.py | 47 +++++++++++++++++++---------------- 5 files changed, 84 insertions(+), 45 deletions(-) diff --git a/mm/mempool/mempool.c b/mm/mempool/mempool.c index 4ea7a9e7833..ed8dd6a9e66 100644 --- a/mm/mempool/mempool.c +++ b/mm/mempool/mempool.c @@ -187,6 +187,7 @@ static void mempool_memdump_callback(FAR struct mempool_s *pool, FAR const void *input, FAR void *output) { size_t blocksize = MEMPOOL_REALBLOCKSIZE(pool); + size_t overhead = blocksize - pool->blocksize; FAR const struct mm_memdump_s *dump = input; if (buf->magic == MEMPOOL_MAGIC_FREE) @@ -206,8 +207,8 @@ static void mempool_memdump_callback(FAR struct mempool_s *pool, FAR const char *tmp = ""; # endif - syslog(LOG_INFO, "%6d%12zu%12lu%*p%s\n", - buf->pid, blocksize, buf->seqno, + syslog(LOG_INFO, "%6d%12zu%9zu%12lu%*p %s\n", + buf->pid, blocksize, overhead, buf->seqno, BACKTRACE_PTR_FMT_WIDTH, ((FAR char *)buf - pool->blocksize), tmp); } @@ -219,11 +220,12 @@ mempool_memdump_free_callback(FAR struct mempool_s *pool, FAR const void *input, FAR void *output) { size_t blocksize = MEMPOOL_REALBLOCKSIZE(pool); + size_t overhead = blocksize - pool->blocksize; if (buf->magic == MEMPOOL_MAGIC_FREE) { - syslog(LOG_INFO, "%12zu%*p\n", - blocksize, BACKTRACE_PTR_FMT_WIDTH, + syslog(LOG_INFO, "%12zu%9zu%*p\n", + blocksize, overhead, BACKTRACE_PTR_FMT_WIDTH, ((FAR char *)buf - pool->blocksize)); } } @@ -587,11 +589,12 @@ void mempool_memdump(FAR struct mempool_s *pool, } #else size_t blocksize = MEMPOOL_REALBLOCKSIZE(pool); + size_t overhead = blocksize - pool->blocksize; /* Avoid race condition */ - syslog(LOG_INFO, "%12zu%*p skip block dump\n", - blocksize, BACKTRACE_PTR_FMT_WIDTH, pool); + syslog(LOG_INFO, "%12zu%9zu%*p skip block dump\n", + blocksize, overhead, BACKTRACE_PTR_FMT_WIDTH, pool); #endif } diff --git a/mm/mm_heap/mm_memdump.c b/mm/mm_heap/mm_memdump.c index 11fc5192866..ed977e03226 100644 --- a/mm/mm_heap/mm_memdump.c +++ b/mm/mm_heap/mm_memdump.c @@ -60,13 +60,14 @@ struct mm_memdump_priv_s static void memdump_allocnode(FAR struct mm_allocnode_s *node) { size_t nodesize = MM_SIZEOF_NODE(node); + size_t overhead = MM_ALLOCNODE_OVERHEAD; #if CONFIG_MM_BACKTRACE < 0 - syslog(LOG_INFO, "%12zu%*p\n", - nodesize, BACKTRACE_PTR_FMT_WIDTH, + syslog(LOG_INFO, "%12zu%9zu%*p\n", + nodesize, overhead, BACKTRACE_PTR_FMT_WIDTH, (FAR const char *)node + MM_SIZEOF_ALLOCNODE); #elif CONFIG_MM_BACKTRACE == 0 - syslog(LOG_INFO, "%6d%12zu%12lu%*p\n", - node->pid, nodesize, node->seqno, + syslog(LOG_INFO, "%6d%12zu%9zu%12lu%*p\n", + node->pid, nodesize, overhead, node->seqno, BACKTRACE_PTR_FMT_WIDTH, (FAR const char *)node + MM_SIZEOF_ALLOCNODE); #else @@ -75,8 +76,8 @@ static void memdump_allocnode(FAR struct mm_allocnode_s *node) backtrace_format(buf, sizeof(buf), node->backtrace, CONFIG_MM_BACKTRACE); - syslog(LOG_INFO, "%6d%12zu%12lu%*p %s\n", - node->pid, nodesize, node->seqno, + syslog(LOG_INFO, "%6d%12zu%9zu%12lu%*p %s\n", + node->pid, nodesize, overhead, node->seqno, BACKTRACE_PTR_FMT_WIDTH, (FAR const char *)node + MM_SIZEOF_ALLOCNODE, buf); #endif @@ -202,8 +203,8 @@ static void memdump_handler(FAR struct mm_allocnode_s *node, FAR void *arg) priv->info.aordblks++; priv->info.uordblks += nodesize; - syslog(LOG_INFO, "%12zu%*p\n", - nodesize, BACKTRACE_PTR_FMT_WIDTH, + syslog(LOG_INFO, "%12zu%9zu%*p\n", + nodesize, MM_ALLOCNODE_OVERHEAD, BACKTRACE_PTR_FMT_WIDTH, ((FAR char *)node + MM_SIZEOF_ALLOCNODE)); } } @@ -288,10 +289,13 @@ void mm_memdump(FAR struct mm_heap_s *heap, } #if CONFIG_MM_BACKTRACE < 0 - syslog(LOG_INFO, "%12s%*s\n", "Size", BACKTRACE_PTR_FMT_WIDTH, "Address"); + syslog(LOG_INFO, "%12s%9s%*s\n", "Size", "Overhead", + BACKTRACE_PTR_FMT_WIDTH, + "Address"); #else - syslog(LOG_INFO, "%6s%12s%12s%*s %s\n", "PID", "Size", "Sequence", - BACKTRACE_PTR_FMT_WIDTH, "Address", "Backtrace"); + syslog(LOG_INFO, "%6s%12s%9s%12s%*s %s\n", "PID", "Size", "Overhead", + "Sequence", BACKTRACE_PTR_FMT_WIDTH, + "Address", "Backtrace"); #endif memdump_dump_pool(&priv, heap); diff --git a/tools/gdb/nuttxgdb/memdump.py b/tools/gdb/nuttxgdb/memdump.py index 7d454522eea..995dd0ab1dd 100644 --- a/tools/gdb/nuttxgdb/memdump.py +++ b/tools/gdb/nuttxgdb/memdump.py @@ -90,7 +90,9 @@ def group_nodes( def print_node(node: MMNodeDump, alive, count=1, formatter=None, no_backtrace=False): - formatter = formatter or "{:>1} {:>4} {:>12} {:>12} {:>12} {:>14} {:>18} {:}\n" + formatter = ( + formatter or "{:>1} {:>4} {:>12} {:>12} {:>12} {:>9} {:>14} {:>18} {:}\n" + ) gdb.write( formatter.format( "\x1b[33;1m*\x1b[m" if not alive else "", @@ -98,6 +100,7 @@ def print_node(node: MMNodeDump, alive, count=1, formatter=None, no_backtrace=Fa count, node.pid, node.nodesize, + node.overhead, node.seqno, hex(node.address), "", @@ -105,15 +108,27 @@ def print_node(node: MMNodeDump, alive, count=1, formatter=None, no_backtrace=Fa ) if mm.CONFIG_MM_BACKTRACE and not no_backtrace: - leading = formatter.format("", "", "", "", "", "", "", "")[:-1] + leading = formatter.format("", "", "", "", "", "", "", "", "")[:-1] btformat = leading + "{1:<48}{2}\n" if node.backtrace and node.backtrace[0]: gdb.write(f"{utils.Backtrace(node.backtrace, formatter=btformat)}\n") def print_header(formatter=None): - formatter = formatter or "{:>1} {:>4} {:>12} {:>12} {:>12} {:>14} {:>18} {:}\n" - head = ("", "Pool", "CNT", "PID", "Size", "Seqno", "Address", "Backtrace") + formatter = ( + formatter or "{:>1} {:>4} {:>12} {:>12} {:>12} {:>9} {:>14} {:>18} {:}\n" + ) + head = ( + "", + "Pool", + "CNT", + "PID", + "Size", + "Overhead", + "Seqno", + "Address", + "Backtrace", + ) gdb.write(formatter.format(*head)) diff --git a/tools/gdb/nuttxgdb/mm.py b/tools/gdb/nuttxgdb/mm.py index 7ff7164967b..f484c1b7310 100644 --- a/tools/gdb/nuttxgdb/mm.py +++ b/tools/gdb/nuttxgdb/mm.py @@ -634,8 +634,20 @@ class MMPoolInfo(gdb.Command): gdb.write(f"Total {count} pools\n") name_max = max(len(pool.name) for pool in pools) + 11 # 11: "@0x12345678" - formatter = "{:>%d} {:>11} {:>9} {:>9} {:>9} {:>9} {:>9}\n" % name_max - head = ("", "total", "bsize", "nused", "nfree", "nifree", "nwaiter") + formatter = ( + "{:>%d} {:>11} {:>9} {:>9} {:>9} {:>9} {:>9} {:>9} {:>9}\n" % name_max + ) + head = ( + "", + "total", + "blocksize", + "bsize", + "overhead", + "nused", + "nfree", + "nifree", + "nwaiter", + ) gdb.write(formatter.format(*head)) for pool in pools: @@ -643,7 +655,9 @@ class MMPoolInfo(gdb.Command): formatter.format( f"{pool.name}@{pool.address:#x}", pool.total, + pool.blocksize, pool.size, + pool.overhead, pool.nused, pool.nfree, pool.nifree, diff --git a/tools/parsememdump.py b/tools/parsememdump.py index ee0b3968153..f5faf56587c 100755 --- a/tools/parsememdump.py +++ b/tools/parsememdump.py @@ -28,7 +28,7 @@ This program will help you analyze memdump log files, analyze the number of occurrences of backtrace, and output stack information memdump log files need this format: -pid size seq addr mem +pid size overhead seq addr mem """ @@ -37,26 +37,27 @@ class dump_line: self.mem = [] self.err = False self.cnt = 1 - tmp = re.search("( \d+ )", line_str) - if tmp is None: - self.err = True - return - self.pid = int(tmp.group(0)[1:]) - tmp = re.search("( \d+ )", line_str[tmp.span()[1] :]) - if tmp is None: - self.err = True - return - self.size = int(tmp.group(0)[1:]) - tmp = re.search("( \d+ )", line_str[tmp.span()[1] :]) - if tmp is None: + self.pid = None + self.size = None + self.overhead = None + self.seq = None + self.addr = None + self.parse_line(line_str) + + def parse_line(self, line_str): + match = re.search( + r"\s+(\d+)\s+(\d+)\s+(\d+)\s+(\d+)\s+((?:\s+0x[0-9a-fA-F]+)+)", line_str + ) + if match: + self.pid = int(match.group(1)) + self.size = int(match.group(2)) + self.overhead = int(match.group(3)) + self.seq = int(match.group(4)) + addresses = match.group(5).split() + self.addr = addresses[0] + self.mem = addresses[1:] + else: self.err = True - return - self.seq = int(tmp.group(0)[1:]) - - tmp = re.findall("0x([0-9a-fA-F]+)", line_str[tmp.span()[1] :]) - self.addr = tmp[0] - for s in tmp[1:]: - self.mem.append(s) class log_output: @@ -204,7 +205,7 @@ if __name__ == "__main__": total_size += size log.output("all used memory %-6d\n" % (total_size)) - log.output("cnt size pid addr mem\n") + log.output("cnt size pid overhead addr mem\n") mems = [] for line in lines: @@ -221,7 +222,9 @@ if __name__ == "__main__": db = addr2line_db(mem=mems, ncpu=ncpu, prefix=args.prefix[0], file=args.elffile[0]) for t in lines: addr2line_str = "" - log.output("%-4d %-6d %-3d %s " % (t.cnt, t.size, t.pid, t.addr)) + log.output( + "%-4d %-6d %-6d %-3d %s " % (t.cnt, t.size, t.overhead, t.pid, t.addr) + ) if t.mem == []: log.output("\n") continue -- Gitee From c4b36f02784c1ad6648e526d234866db4c8481f6 Mon Sep 17 00:00:00 2001 From: xuxingliang Date: Thu, 21 Nov 2024 16:38:16 +0800 Subject: [PATCH 011/235] gdb: print trace back when some modules failed to load VELAPLATFO-47806 Change-Id: I685457ace102059d820fef3b7d62126343abc703 Signed-off-by: xuxingliang --- tools/gdb/nuttxgdb/__init__.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tools/gdb/nuttxgdb/__init__.py b/tools/gdb/nuttxgdb/__init__.py index 22ec8300317..e8fa48c8056 100644 --- a/tools/gdb/nuttxgdb/__init__.py +++ b/tools/gdb/nuttxgdb/__init__.py @@ -19,6 +19,7 @@ ############################################################################ import importlib +import traceback from os import path import gdb @@ -51,6 +52,7 @@ def register_commands(event): module = importlib.import_module(f"{__package__}.{m}") except Exception as e: gdb.write(f"\x1b[31;1mIgnore module: {m}, error: {e}\n\x1b[m") + traceback.print_exc() return for c in module.__dict__.values(): -- Gitee From e0bacf9058f2b61bff1ca85ef3c427ccd7f47908 Mon Sep 17 00:00:00 2001 From: xuxingliang Date: Thu, 21 Nov 2024 16:38:57 +0800 Subject: [PATCH 012/235] gdb/mm: fix memdump when mempool backtrace is disabled VELAPLATFO-47806 Change-Id: I785f1b8c1931283d08f0a77e4a1f76e79a2c6e6e Signed-off-by: xuxingliang --- tools/gdb/nuttxgdb/mm.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/tools/gdb/nuttxgdb/mm.py b/tools/gdb/nuttxgdb/mm.py index f484c1b7310..c0da3097241 100644 --- a/tools/gdb/nuttxgdb/mm.py +++ b/tools/gdb/nuttxgdb/mm.py @@ -93,10 +93,13 @@ class MemPoolBlock: @property def is_free(self) -> bool: + if CONFIG_MM_BACKTRACE < 0: + return False + if not self._magic: self._magic = int(self.blk["magic"]) - return CONFIG_MM_BACKTRACE and self._magic != self.MAGIC_ALLOC + return self._magic != self.MAGIC_ALLOC @property def seqno(self) -> int: -- Gitee From 1418be4163de67c519cde40100087bfe2da10c13 Mon Sep 17 00:00:00 2001 From: xuxingliang Date: Thu, 21 Nov 2024 20:32:30 +0800 Subject: [PATCH 013/235] gdb/memdump: reorganize the memdump parameters VELAPLATFO-47806 Make the dump_nodes etc more common to use. Change-Id: I8dd3e65fe3690df6bac21ff632e322af8a7a7927 Signed-off-by: xuxingliang --- tools/gdb/nuttxgdb/memdump.py | 187 ++++++++++++++++++---------------- tools/gdb/nuttxgdb/memleak.py | 2 +- 2 files changed, 100 insertions(+), 89 deletions(-) diff --git a/tools/gdb/nuttxgdb/memdump.py b/tools/gdb/nuttxgdb/memdump.py index 995dd0ab1dd..d5bcab8768b 100644 --- a/tools/gdb/nuttxgdb/memdump.py +++ b/tools/gdb/nuttxgdb/memdump.py @@ -44,8 +44,7 @@ class MMNodeDump(Protocol): def read_memory(self) -> memoryview: ... -def dump_nodes( - heaps: List[mm.MMHeap], +def filter_node( pid=None, nodesize=None, used=None, @@ -53,30 +52,41 @@ def dump_nodes( seqmin=None, seqmax=None, orphan=None, - no_heap=False, - no_pool=False, no_pid=None, + no_heap=None, + no_pool=None, +) -> bool: + return lambda node: ( + (pid is None or node.pid == pid) + and (no_pid is None or node.pid != no_pid) + and (nodesize is None or node.nodesize == nodesize) + and (not used or not node.is_free) + and (not free or node.is_free) + and (seqmin is None or node.seqno >= seqmin) + and (seqmax is None or node.seqno <= seqmax) + and (not orphan or node.is_orphan) + ) + + +def dump_nodes( + heaps: List[mm.MMHeap], + filters=None, ) -> Generator[MMNodeDump, None, None]: - def filter_node(node: MMNodeDump) -> bool: - return ( - (pid is None or node.pid == pid) - and (no_pid is None or node.pid != no_pid) - and (nodesize is None or node.nodesize == nodesize) - and (not used or not node.is_free) - and (not free or node.is_free) - and (seqmin is None or node.seqno >= seqmin) - and (seqmax is None or node.seqno <= seqmax) - and (not orphan or node.is_orphan) - ) + no_heap = filters and filters.get("no_heap") + no_pool = filters and filters.get("no_heap") if not no_heap: - yield from (node for heap in heaps for node in filter(filter_node, heap.nodes)) + yield from ( + node + for heap in heaps + for node in filter(filter_node(**filters), heap.nodes) + ) if not no_pool: yield from ( blk for pool in mm.get_pools(heaps) - for blk in filter(filter_node, pool.blks) + for blk in filter(filter_node(**filters), pool.blks) ) @@ -146,18 +156,6 @@ class MMDump(gdb.Command): # define memdump as mm dump utils.alias("memdump", "mm dump") - def find(self, heaps: List[mm.MMHeap], addr): - """Find the node that contains the address""" - # Search pools firstly. - for pool in mm.get_pools(heaps): - if blk := pool.find(addr): - return blk - - # Search heaps - for heap in heaps: - if node := heap.find(addr): - return node - def parse_args(self, arg): parser = argparse.ArgumentParser(description=self.__doc__) parser.add_argument( @@ -165,7 +163,7 @@ class MMDump(gdb.Command): "--address", type=str, default=None, - help="The address to inspect", + help="Find the node that contains the address and exit", ) parser.add_argument( @@ -213,6 +211,12 @@ class MMDump(gdb.Command): action="store_true", help="Do not print backtrace", ) + parser.add_argument( + "--no-reverse", + "--nor", + action="store_true", + help="Do not reverse the sort result", + ) # add option to sort the node by size or count parser.add_argument( @@ -228,38 +232,52 @@ class MMDump(gdb.Command): except SystemExit: return + def find_address(self, addr, heap=None, log=None): + """Find the node that contains the address from memdump log or live dump.""" + addr = int(gdb.parse_and_eval(addr)) + heaps = [mm.MMHeap(gdb.parse_and_eval(heap))] if heap else mm.get_heaps() + + # Find pool firstly + node = next( + (blk for pool in mm.get_pools(heaps) if (blk := pool.find(addr))), None + ) + + # Try heap if not found in pool + node = node or next((node for heap in heaps if (node := heap.find(addr))), None) + + return addr, node + + def collect_nodes(self, heap, log=None, filters=None): + heaps = [mm.MMHeap(gdb.parse_and_eval(heap))] if heap else mm.get_heaps() + nodes = dump_nodes(heaps, filters) + + return nodes + def invoke(self, arg: str, from_tty: bool) -> None: if not (args := self.parse_args(arg)): return - heaps = ( - [mm.MMHeap(gdb.parse_and_eval(args.heap))] if args.heap else mm.get_heaps() - ) - pids = [int(tcb["pid"]) for tcb in utils.get_tcbs()] - print_header() + pids = [int(tcb["pid"]) for tcb in utils.get_tcbs()] + def printnode(node, count): print_node(node, node.pid in pids, count, no_backtrace=args.no_backtrace) + # Find the node by address, find directly and then quit if args.address: - addr = int(gdb.parse_and_eval(args.address)) - # Address specified, find and return directly. - node = None - for pool in mm.get_pools(heaps): - if node := pool.find(addr): - break - - if node or (node := self.find(heaps, addr)): - printnode(node, 1) - source = "Pool" if node.from_pool else "Heap" - print(f"{addr: #x} found belongs to {source} {node}") - if node.prevnode: - print(f"prevnode: {node.prevnode}") - if node.nextnode: - print(f"nextnode: {node.nextnode}") - else: + addr, node = self.find_address(args.address, args.heap, args.log) + if not node: print(f"Address {addr:#x} not found in any heap") + else: + source = "Pool" if node.from_pool else "Heap" + printnode(node, 1) + print(f"{addr: #x} found belongs to {source} - {node}") + + if node.prevnode: + print(f"prevnode: {node.prevnode}") + if node.nextnode: + print(f"nextnode: {node.nextnode}") return filters = { @@ -270,21 +288,11 @@ class MMDump(gdb.Command): "seqmin": args.min, "seqmax": args.max, "orphan": args.orphan, + "no_heap": args.no_heap, + "no_pool": args.no_pool, } - heap_nodes = dump_nodes(heaps, **filters, no_heap=args.no_heap, no_pool=True) - pool_nodes = dump_nodes(heaps, **filters, no_heap=True, no_pool=args.no_pool) - - if args.biggest: - # Find the biggest nodes, only applicable to heaps - nodes = sorted( - heap_nodes, - key=lambda node: node.nodesize, - reverse=True, - ) - for node in nodes[: args.top]: - print(f"node@{node.address}: {node}") - return + nodes = self.collect_nodes(args.heap, log=args.log, filters=filters) sort_method = { "count": lambda node: 1, @@ -294,41 +302,44 @@ class MMDump(gdb.Command): "address": lambda node: node.address, } - def sort_nodes(nodes): - nodes = sorted(nodes, key=sort_method[args.sort], reverse=True) + def sort_nodes(nodes, sort=None): + sort = sort or args.sort + nodes = sorted(nodes, key=sort_method[sort], reverse=not args.no_reverse) if args.top is not None: nodes = nodes[: args.top] if args.top > 0 else nodes[args.top :] return nodes + if args.biggest: + # Dump the biggest node is same as sort by nodesize and do not group them + args.sort = "nodesize" + args.no_group = True + if args.no_group: # Print nodes without grouping - nodes = list(heap_nodes) - nodes.extend(pool_nodes) + nodes = list(nodes) for node in sort_nodes(nodes): printnode(node, 1) gdb.write(f"Total blks: {len(nodes)}\n") - return - - # Finally group the nodes and then print - - grouped: Dict[MMNodeDump, MMNodeDump] = defaultdict(list) - grouped = group_nodes(heap_nodes) - grouped = group_nodes(pool_nodes, grouped) - - # Replace the count and size to count grouped nodes - sort_method["count"] = lambda node: len(grouped[node]) - sort_method["size"] = lambda node: node.nodesize * len(grouped[node]) - total_blk = total_size = 0 - for node in sort_nodes(grouped.keys()): - count = len(grouped[node]) - total_blk += count - if node.pid != mm.PID_MM_MEMPOOL: - total_size += count * node.nodesize - printnode(node, count) - - print(f"Total {total_blk} blks, {total_size} bytes") + else: + # Group the nodes and then print + + grouped: Dict[MMNodeDump, MMNodeDump] = defaultdict(list) + grouped = group_nodes(nodes) + + # Replace the count and size to count grouped nodes + sort_method["count"] = lambda node: len(grouped[node]) + sort_method["size"] = lambda node: node.nodesize * len(grouped[node]) + total_blk = total_size = 0 + for node in sort_nodes(grouped.keys()): + count = len(grouped[node]) + total_blk += count + if node.pid != mm.PID_MM_MEMPOOL: + total_size += count * node.nodesize + printnode(node, count) + + print(f"Total {total_blk} blks, {total_size} bytes") class MMfrag(gdb.Command): diff --git a/tools/gdb/nuttxgdb/memleak.py b/tools/gdb/nuttxgdb/memleak.py index 431f4b9c5cc..2a4b2455b62 100644 --- a/tools/gdb/nuttxgdb/memleak.py +++ b/tools/gdb/nuttxgdb/memleak.py @@ -116,7 +116,7 @@ class MMLeak(gdb.Command): sorted_addr = set() t = time.time() print("Gather memory nodes...", flush=True, end="") - for node in memdump.dump_nodes(heaps, used=True, no_pid=mm.PID_MM_MEMPOOL): + for node in memdump.dump_nodes(heaps, {"no_pid": mm.PID_MM_MEMPOOL}): nodes_dict[node.address] = node sorted_addr.add(node.address) -- Gitee From a77c12c1b650fab458c335c92ad2ff28628e28e9 Mon Sep 17 00:00:00 2001 From: xuxingliang Date: Thu, 21 Nov 2024 20:34:03 +0800 Subject: [PATCH 014/235] gdb/memdump: add option to parse memdump log from device VELAPLATFO-47806 Change-Id: I643b5410011df4ae009628b5a4cb6995ddcf95b0 Signed-off-by: xuxingliang --- tools/gdb/nuttxgdb/memdump.py | 96 +++++++++++++++++++++++++++++++---- 1 file changed, 86 insertions(+), 10 deletions(-) diff --git a/tools/gdb/nuttxgdb/memdump.py b/tools/gdb/nuttxgdb/memdump.py index d5bcab8768b..214bad511b1 100644 --- a/tools/gdb/nuttxgdb/memdump.py +++ b/tools/gdb/nuttxgdb/memdump.py @@ -19,6 +19,7 @@ ############################################################################ import argparse +import re from collections import defaultdict from typing import Dict, Generator, List, Protocol, Tuple @@ -73,7 +74,7 @@ def dump_nodes( filters=None, ) -> Generator[MMNodeDump, None, None]: no_heap = filters and filters.get("no_heap") - no_pool = filters and filters.get("no_heap") + no_pool = filters and filters.get("no_pool") if not no_heap: yield from ( @@ -148,6 +149,64 @@ def get_heaps(args_heap=None) -> List[mm.MMHeap]: return mm.get_heaps() +def parse_memdump_log(logfile, filters=None) -> Generator[MMNodeDump, None, None]: + nodes = [] + + class DumpNode(MMNodeDump): + def __init__(self, address, nodesize, seqno, pid, backtrace, is_free, overhead): + # C code dump the start address of the node, convert it the actual start address + self.address = address - overhead + self.nodesize = nodesize + self.seqno = seqno + self.pid = pid + self.backtrace = backtrace + self.overhead = overhead + self.is_free = False + self.from_pool = False + + def __repr__(self) -> str: + return f"node@{self.address:#x}: size:{self.nodesize} seq:{self.seqno} pid:{self.pid} " + + def contains(self, addr: int) -> bool: + return self.address <= addr < self.address + self.nodesize + + @property + def prevnode(self): + return next( + (node for node in nodes if node.contains(self.address - 1)), None + ) + + @property + def nextnode(self): + address = self.address + self.nodesize # address of the next node + return next( + (node for node in nodes if node.address == address), + None, + ) + + with open(logfile) as f: + for line in f: + match = re.search( + r"\s+(\d+)\s+(\d+)\s+(\d+)\s+(\d+)\s+((?:\s+0x[0-9a-fA-F]+)+)", line + ) + if not match: + continue + + try: + pid = int(match.group(1)) + size = int(match.group(2)) + overhead = int(match.group(3)) + seq = int(match.group(4)) + addresses = match.group(5).split() + addr = int(addresses[0], base=16) + mem = tuple(int(addr, base=16) for addr in addresses[1:]) + nodes.append(DumpNode(addr, size, seq, pid, mem, False, overhead)) + except Exception as e: + print(f"Error parsing line: {line}, {e}") + + return filter(filter_node(**filters), nodes) if filters else nodes + + class MMDump(gdb.Command): """Dump memory manager heap""" @@ -166,6 +225,14 @@ class MMDump(gdb.Command): help="Find the node that contains the address and exit", ) + parser.add_argument( + "-l", + "--log", + type=str, + default=None, + help="Use the memdump log file generated by memdump command on device instead of live dump", + ) + parser.add_argument( "--heap", type=str, @@ -235,21 +302,30 @@ class MMDump(gdb.Command): def find_address(self, addr, heap=None, log=None): """Find the node that contains the address from memdump log or live dump.""" addr = int(gdb.parse_and_eval(addr)) - heaps = [mm.MMHeap(gdb.parse_and_eval(heap))] if heap else mm.get_heaps() + if log: + nodes = parse_memdump_log(log) + node = next((node for node in nodes if node.contains(addr)), None) + else: + heaps = [mm.MMHeap(gdb.parse_and_eval(heap))] if heap else mm.get_heaps() - # Find pool firstly - node = next( - (blk for pool in mm.get_pools(heaps) if (blk := pool.find(addr))), None - ) + # Find pool firstly + node = next( + (blk for pool in mm.get_pools(heaps) if (blk := pool.find(addr))), None + ) - # Try heap if not found in pool - node = node or next((node for heap in heaps if (node := heap.find(addr))), None) + # Try heap if not found in pool + node = node or next( + (node for heap in heaps if (node := heap.find(addr))), None + ) return addr, node def collect_nodes(self, heap, log=None, filters=None): - heaps = [mm.MMHeap(gdb.parse_and_eval(heap))] if heap else mm.get_heaps() - nodes = dump_nodes(heaps, filters) + if log: + nodes = parse_memdump_log(log, filters=filters) + else: + heaps = [mm.MMHeap(gdb.parse_and_eval(heap))] if heap else mm.get_heaps() + nodes = dump_nodes(heaps, filters) return nodes -- Gitee From 4f6abed329b75f68de7414ef4bea302947ba80b8 Mon Sep 17 00:00:00 2001 From: xuxingliang Date: Thu, 21 Nov 2024 20:49:21 +0800 Subject: [PATCH 015/235] gdb/memdump: add option to exclude nodes from specific PID VELAPLATFO-47806 This is useful to exclude memory nodes for mempool. E.g. (gdb) mm dump --nob --top 5 --sort size --nop --no-pid -1 Pool CNT PID Size Overhead Seqno Address Backtrace H 1 0 16777264 44 13 0x41a79010 H 2 160 1536048 44 1129827490 0x41d6aad0 H 1 45374 1536176 44 1129829080 0x45ef1010 H 3 141 408440 44 145817 0x43905bf0 H 7 158 131120 44 32955 0x4308d090 Total 14 blks, 23528696 bytes (gdb) mm dump --nob --top 5 --sort size --nop Pool CNT PID Size Overhead Seqno Address Backtrace H 1 0 16777264 44 13 0x41a79010 * H 6 -1 1048640 44 116954 0x436a0fd0 * H 5 -1 1048640 44 146821 0x43b24fd0 * H 3 -1 1048640 44 66161 0x4335bfd0 * H 3 -1 1048640 44 156337 0x43d3ffd0 Total 18 blks, 16777264 bytes Change-Id: I8329f68d6ba48fbbc7310648abf4a73e2b26acb4 Signed-off-by: xuxingliang --- tools/gdb/nuttxgdb/memdump.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/tools/gdb/nuttxgdb/memdump.py b/tools/gdb/nuttxgdb/memdump.py index 214bad511b1..aadd72218cf 100644 --- a/tools/gdb/nuttxgdb/memdump.py +++ b/tools/gdb/nuttxgdb/memdump.py @@ -284,6 +284,9 @@ class MMDump(gdb.Command): action="store_true", help="Do not reverse the sort result", ) + parser.add_argument( + "--no-pid", type=int, default=None, help="Exclude nodes from this PID" + ) # add option to sort the node by size or count parser.add_argument( @@ -366,6 +369,7 @@ class MMDump(gdb.Command): "orphan": args.orphan, "no_heap": args.no_heap, "no_pool": args.no_pool, + "no_pid": args.no_pid, } nodes = self.collect_nodes(args.heap, log=args.log, filters=filters) -- Gitee From c455c429ccbecbbfa5aa75b8c4867588a01b2990 Mon Sep 17 00:00:00 2001 From: xuxingliang Date: Mon, 25 Nov 2024 12:13:40 +0800 Subject: [PATCH 016/235] nuttxgdb: fix memdump busyloop when nodesize is 0 VELAPLATFO-48106 Change-Id: Ic7b0c404b5d0d50369c4577dc5ef6ebc73bc38b5 Signed-off-by: xuxingliang --- mm/mm_heap/mm_foreach.c | 1 + tools/gdb/nuttxgdb/mm.py | 5 ++++- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/mm/mm_heap/mm_foreach.c b/mm/mm_heap/mm_foreach.c index 9be84a9848d..a0d4dc9e578 100644 --- a/mm/mm_heap/mm_foreach.c +++ b/mm/mm_heap/mm_foreach.c @@ -81,6 +81,7 @@ void mm_foreach(FAR struct mm_heap_s *heap, mm_node_handler_t handler, node = (FAR struct mm_allocnode_s *)((FAR char *)node + nodesize)) { nodesize = MM_SIZEOF_NODE(node); + DEBUGASSERT(nodesize >= MM_SIZEOF_ALLOCNODE); minfo("region=%d node=%p size=%zu preceding=%u (%c %c)\n", region, node, nodesize, (unsigned int)node->preceding, MM_PREVNODE_IS_FREE(node) ? 'F' : 'A', diff --git a/tools/gdb/nuttxgdb/mm.py b/tools/gdb/nuttxgdb/mm.py index c0da3097241..bb923ecd5e1 100644 --- a/tools/gdb/nuttxgdb/mm.py +++ b/tools/gdb/nuttxgdb/mm.py @@ -466,6 +466,9 @@ class MMNode(gdb.Value, p.MMFreeNode): @property def nextnode(self) -> MMNode: + if not self.nodesize: + return None + addr = int(self.address) + self.nodesize type = utils.lookup_type("struct mm_freenode_s").pointer() # Use gdb.Value for better performance @@ -551,7 +554,7 @@ class MMHeap(Value, p.MMHeap): def nodes(self) -> Generator[MMNode, None, None]: for start, end in self.regions: node = start - while node.address <= end.address: + while node and node.address <= end.address: yield node node = node.nextnode -- Gitee From 1b668f914d1f0a76769ca2d727f0efd4066049e9 Mon Sep 17 00:00:00 2001 From: huangyin5 Date: Thu, 2 Jan 2025 11:29:47 +0800 Subject: [PATCH 017/235] gdb/libuv: add uv dump loop & handle_queue VELAPLATFO-45245 Cmd for example: uv dump loop -l 0x41883020 Output: uv_loop address: 0x0x41883020, main content of loop: { data: 0x0 active_handles: 1 active_reqs: {unused = 0x0, count = 0} stop_flag: 0 close_flag: 0 flags: 0 backend_fd: -1 nwatchers: 15 nfds: 2 emfile_fd: -1 poll_fds: 0x42c2ab98 poll_fds_used: 2 poll_fds_size: 64 poll_fds_iterating: 0 '\000' } Cmd for example: uv dump handle_queue -l 0xf4c6a580 Output: [0] [--I] UV_SIGNAL 0xf4c6a71c backtrace: {0xf79cc34d <__interceptor_backtrace(void**, int)+61>, 0x66a8b7f4 , 0x64e328d8 , 0x64e002c9 , 0x6551a0d4 , 0x65561be2 , 0x65554d1e , 0x6554dd60 } [1] [-AI] UV_ASYNC 0xf4c6a5e4 backtrace: {0xf79cc34d <__interceptor_backtrace(void**, int)+61>, 0x66a8b7f4 , 0x64e328d8 , 0x64e002c9 , 0x6551a0d4 , 0x655100bb , 0x6554deff , 0x5e5635ec } Change-Id: Iac80730a417547e059b3804ab948f2af0e5ae1c5 Signed-off-by: huangyin5 --- tools/gdb/nuttxgdb/libuv.py | 162 +++++++++++++++++++++++++++++++++++ tools/gdb/nuttxgdb/prefix.py | 7 ++ 2 files changed, 169 insertions(+) create mode 100644 tools/gdb/nuttxgdb/libuv.py diff --git a/tools/gdb/nuttxgdb/libuv.py b/tools/gdb/nuttxgdb/libuv.py new file mode 100644 index 00000000000..7be299581cd --- /dev/null +++ b/tools/gdb/nuttxgdb/libuv.py @@ -0,0 +1,162 @@ +############################################################################ +# apps/system/libuv/gdb/libuv.py +# +# Licensed to the Apache Software Foundation (ASF) under one or more +# contributor license agreements. See the NOTICE file distributed with +# this work for additional information regarding copyright ownership. The +# ASF licenses this file to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance with the +# License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# +############################################################################ + +import argparse + +import gdb + +from . import lists, utils + + +class UVQueue(lists.NxList): + def __init__( + self, list: gdb.Value, container_type=None, member=None, reverse=False + ): + super().__init__(list, container_type, member, reverse) + + def _get_first(self): + return self.list + + def _get_next(self, node): + return node["next"] if node["next"] != self.list else None + + def _get_prev(self, node): + return node["prev"] if node["prev"] != self.list else None + + +class UVDump(gdb.Command): + """Dump the information of uv_loop & handle_queue & uv_worker in libuv""" + + def __init__(self): + super(UVDump, self).__init__("uv dump", gdb.COMMAND_USER) + + def dump_loop(self, loop): + if not loop: + return + gdb.write("### dump uv_loop ###\n") + gdb.write(f"uv_loop address: 0x{loop}, main content of loop: {{\n") + gdb.write(f" data: {loop['data']}\n") + gdb.write(f" active_handles: {loop['active_handles']}\n") + gdb.write(f" active_reqs: {loop['active_reqs']}\n") + gdb.write(f" stop_flag: {loop['stop_flag']}\n") + gdb.write(f" close_flag: {loop['close_flag']}\n") + gdb.write(f" flags: {loop['flags']}\n") + gdb.write(f" backend_fd: {loop['backend_fd']}\n") + gdb.write(f" nwatchers: {loop['nwatchers']}\n") + gdb.write(f" nfds: {loop['nfds']}\n") + gdb.write(f" emfile_fd: {loop['emfile_fd']}\n") + gdb.write(f" poll_fds: {loop['poll_fds']}\n") + gdb.write(f" poll_fds_used: {loop['poll_fds_used']}\n") + gdb.write(f" poll_fds_size: {loop['poll_fds_size']}\n") + gdb.write(f" poll_fds_iterating: {loop['poll_fds_iterating']}\n") + gdb.write("}\n") + + return + + def dump_handle_queue(self, loop): + gdb.write("### dump uv_handle queue & backtrace ###\n") + if not loop: + return + head = loop["handle_queue"].address + if not head: + gdb.write("handle queue is None\n") + return + + UV_HANDLE = utils.enum("enum uv_handle_flag") + UV_HANDLE_BACKTRACE = utils.get_symbol_value("UV_HANDLE_BACKTRACE") + flags = [ + (UV_HANDLE.HANDLE_REF, "R"), + (UV_HANDLE.HANDLE_ACTIVE, "A"), + (UV_HANDLE.HANDLE_INTERNAL, "I"), + ] + handle_queue = UVQueue(head, gdb.lookup_type("uv_handle_t"), "handle_queue") + for i, uv_handle in enumerate(handle_queue): + output = "" + for handle, flag in flags: + output += flag if handle.value & uv_handle["flags"] else "-" + gdb.write(f"[{i}] [{output}] {uv_handle['type']} {uv_handle}\n") + if UV_HANDLE_BACKTRACE > 0: + gdb.write(f"backtrace: {uv_handle['backtrace']}\n") + if self.detail: + uv_handle_content = uv_handle.dereference().format_string( + styling=True, pretty_arrays=True, pretty_structs=True + ) + gdb.write(f"uv_handle detail content: {uv_handle_content}\n") + + def get_loop_in_thread(self, thread): + # TODO: find loop variable in current thread + # depends on the bugfix in block.superblock + if not thread: + return None + gdb.write(f"### [TODO] get uv_loop in thread {thread.ptid} ###\n") + + def get_loop(self, args): + if args.loop: + loop = utils.gdb_eval_or_none(args.loop) + if loop is None: + gdb.write("invalid loop ptr\n") + return None + return loop.cast(gdb.lookup_type("uv_loop_t").pointer()) + + if args.pid: + for thread in gdb.selected_inferior().threads(): + if args.pid == thread.ptid[1]: + return self.get_loop_in_thread(thread) + gdb.write(f"invalid pid {args.pid}\n") + else: + return self.get_loop_in_thread(gdb.selected_thread()) + + return None + + def invoke(self, argument: str, from_tty: bool): + parser = argparse.ArgumentParser(description="libuv dump command") + parser.add_argument( + "mode", + nargs="?", + choices=["loop", "handle_queue", "uv_worker"], + default="loop", + ) + parser.add_argument("-p", "--pid", type=int, help="Thread PID of Quickapp") + parser.add_argument("-l", "--loop", type=str, help="address of uv_loop_t") + parser.add_argument( + "-d", + "--detail", + action="store_const", + const=True, + default=False, + help="print more detail information", + ) + + try: + args = parser.parse_args(gdb.string_to_argv(argument)) + except SystemExit: + gdb.write("invalid arguments.\n") + return + + gdb.write(f"### dump libuv in {args.mode} mode ###\n") + + loop = self.get_loop(args) + self.detail = args.detail + + if args.mode == "loop": + self.dump_loop(loop) + elif args.mode == "handle_queue": + self.dump_handle_queue(loop) + return diff --git a/tools/gdb/nuttxgdb/prefix.py b/tools/gdb/nuttxgdb/prefix.py index 08214b1b256..5011392d44b 100644 --- a/tools/gdb/nuttxgdb/prefix.py +++ b/tools/gdb/nuttxgdb/prefix.py @@ -33,3 +33,10 @@ class MMPrefixCommand(gdb.Command): def __init__(self): super().__init__("mm", gdb.COMMAND_USER, prefix=True) + + +class UVDumpPrefix(gdb.Command): + """UV Dump related commands prefix""" + + def __init__(self): + super().__init__("uv", gdb.COMMAND_USER, prefix=True) -- Gitee From 508e0721238f7540fe29b23c6b83556aa8af09ef Mon Sep 17 00:00:00 2001 From: yinshengkai Date: Fri, 15 Nov 2024 12:30:56 +0800 Subject: [PATCH 018/235] tools/gdb: fix checkpatch warning VELAPLATFO-47018 Use Python raw strings to avoid escaping: SyntaxWarning: invalid escape sequence '\?' Change-Id: I98454501775ed7a14aef8b08a51d058523faaf04 Signed-off-by: yinshengkai --- tools/gdb/nuttxgdb/macros.py | 110 +++++++++++++++++------------------ 1 file changed, 55 insertions(+), 55 deletions(-) diff --git a/tools/gdb/nuttxgdb/macros.py b/tools/gdb/nuttxgdb/macros.py index 23a327fd010..81ba2d83cf5 100644 --- a/tools/gdb/nuttxgdb/macros.py +++ b/tools/gdb/nuttxgdb/macros.py @@ -43,60 +43,60 @@ import time from os import path PUNCTUATORS = [ - "\[", - "\]", - "\(", - "\)", - "\{", - "\}", - "\?", - ";", - ",", - "~", - "\.\.\.", - "\.", - "\-\>", - "\-\-", - "\-\=", - "\-", - "\+\+", - "\+\=", - "\+", - "\*\=", - "\*", - "\!\=", - "\!", - "\&\&", - "\&\=", - "\&", - "\/\=", - "\/", - "\%\>", - "%:%:", - "%:", - "%=", - "%", - "\^\=", - "\^", - "\#\#", - "\#", - "\:\>", - "\:", - "\|\|", - "\|\=", - "\|", - "<<=", - "<<", - "<=", - "<:", - "<%", - "<", - ">>=", - ">>", - ">=", - ">", - "\=\=", - "\=", + r"\[", + r"\]", + r"\(", + r"\)", + r"\{", + r"\}", + r"\?", + r";", + r",", + r"~", + r"\.\.\.", + r"\.", + r"\-\>", + r"\-\-", + r"\-\=", + r"\-", + r"\+\+", + r"\+\=", + r"\+", + r"\*\=", + r"\*", + r"\!\=", + r"\!", + r"\&\&", + r"\&\=", + r"\&", + r"\/\=", + r"\/", + r"\%\>", + r"%:%:", + r"%:", + r"%=", + r"%", + r"\^\=", + r"\^", + r"\#\#", + r"\#", + r"\:\>", + r"\:", + r"\|\|", + r"\|\=", + r"\|", + r"<<=", + r"<<", + r"<=", + r"<:", + r"<%", + r"<", + r">>=", + r">>", + r">=", + r">", + r"\=\=", + r"\=", ] @@ -132,7 +132,7 @@ def fetch_macro_info(file): hash = hashlib.md5(f.read()).hexdigest() macros = {} - p = re.compile(".*macro[ ]*:[ ]*([\S]+\(.*?\)|[\w]+)[ ]*(.*)") + p = re.compile(r".*macro[ ]*:[ ]*([\S]+\(.*?\)|[\w]+)[ ]*(.*)") cache = path.join(path.dirname(path.abspath(file)), f"{hash}.json") print(f"Load macro: {cache}") if not path.isfile(cache): -- Gitee From 79f082197f950d68d379c59f60a344e0701977b4 Mon Sep 17 00:00:00 2001 From: yinshengkai Date: Wed, 13 Nov 2024 11:59:22 +0800 Subject: [PATCH 019/235] tools/gdb: move the macros cache files to a temporary directory VELAPLATFO-47018 Change-Id: Icb579affd9e278972d08ca8d042ec1029e427ae5 Signed-off-by: yinshengkai --- tools/gdb/nuttxgdb/macros.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tools/gdb/nuttxgdb/macros.py b/tools/gdb/nuttxgdb/macros.py index 81ba2d83cf5..2e068d595ed 100644 --- a/tools/gdb/nuttxgdb/macros.py +++ b/tools/gdb/nuttxgdb/macros.py @@ -39,6 +39,7 @@ import hashlib import json import os import re +import tempfile import time from os import path @@ -133,7 +134,7 @@ def fetch_macro_info(file): macros = {} p = re.compile(r".*macro[ ]*:[ ]*([\S]+\(.*?\)|[\w]+)[ ]*(.*)") - cache = path.join(path.dirname(path.abspath(file)), f"{hash}.json") + cache = path.join(tempfile.gettempdir(), f"{hash}.json") print(f"Load macro: {cache}") if not path.isfile(cache): t = time.time() -- Gitee From a0e3b9f9dc1b01e0d86b24a66930cee50621e495 Mon Sep 17 00:00:00 2001 From: yinshengkai Date: Wed, 13 Nov 2024 12:33:28 +0800 Subject: [PATCH 020/235] tools/gdb: Add a singleton class for macros VELAPLATFO-47018 Usage: macro = Macro("nuttx/nuttx") print(macro.CONFIG_MM_BACKTRACE) if macro.CONFIG_MM_BACKTRACE: print("mm backtrace is enabled") else: print("mm backtrace is disabled") Change-Id: I7910870b23ed92eb941e404e265f730da7e99c0d Signed-off-by: yinshengkai --- tools/gdb/nuttxgdb/macros.py | 65 ++++++++++++++++++++++++++++++++++++ 1 file changed, 65 insertions(+) diff --git a/tools/gdb/nuttxgdb/macros.py b/tools/gdb/nuttxgdb/macros.py index 2e068d595ed..b98dc4278df 100644 --- a/tools/gdb/nuttxgdb/macros.py +++ b/tools/gdb/nuttxgdb/macros.py @@ -220,3 +220,68 @@ def try_expand(expr, macro): res += do_expand(expr, macro) return "".join(res) + + +class Macro: + """ + This is a singleton class which only initializes once to + cache a context of macro definition which can be queried later + TODO: we only deal with single ELF at the moment for simplicity + If you load more object files while debugging, only the first one gets loaded + will be used to retrieve macro information + + Usage: + macro = Macro("nuttx/nuttx") + print(macro.CONFIG_MM_BACKTRACE) + if macro.CONFIG_MM_BACKTRACE: + print("mm backtrace is enabled") + else: + print("mm backtrace is disabled") + """ + + def __new__(cls, *args, **kwargs): + if not hasattr(cls, "instance"): + cls.instance = super(Macro, cls).__new__(cls) + return cls.instance + + def __init__(self, filename): + self._macro_map = {} + self._file = filename + self._macro_map = fetch_macro_info(filename) + + def is_defined(self, macro_name): + """ + Check if a macro is defined + """ + return macro_name in self._macro_map + + def get_value(self, macro_name, default=None): + """ + Get the value of a macro, return default if macro is not defined + """ + if not self.is_defined(macro_name): + return default + + value = self._macro_map[macro_name] + # Try to convert to numeric type + try: + # Handle hexadecimal + if isinstance(value, str) and value.startswith("0x"): + return int(value, 16) + # Handle integer + return int(value) + except (ValueError, TypeError): + # Return original value if conversion fails + return value + + def __getattr__(self, name): + """ + Allow using dot notation to access macros + """ + return self.get_value(name) + + def __call__(self, macro_name): + """ + Allow using function call syntax to get macro + """ + return self.get_value(macro_name) -- Gitee From 347d8b1db1a9af525b478e02a8f3a4ded8a57867 Mon Sep 17 00:00:00 2001 From: xuxingliang Date: Fri, 22 Nov 2024 21:58:23 +0800 Subject: [PATCH 021/235] gdb/workqueue: add basic workqueue dump support VELAPLATFO-47928 (gdb) worker hpwork@0x40424b40, idle, 2 threads, 0 work lpwork@0x40424a80, idle, 2 threads, 0 work test@0x4045a8c0, running, 2 threads, 2 work Running: kworker_s@0x4045a908 work_s@0x406cf330: 0x0 arg=0x406cf300 Queued: work_s@0x406cf370: 0x402f1954 arg=0x406cf318 work_s@0x406cf3b0: 0x402f1954 arg=0x406cf318 (gdb) Change-Id: I6b93baa9887760318db95ec8d63da7a13768590b Signed-off-by: xuxingliang --- tools/gdb/nuttxgdb/protocols/wqueue.py | 71 +++++++++++ tools/gdb/nuttxgdb/utils.py | 31 ++++- tools/gdb/nuttxgdb/wqueue.py | 170 +++++++++++++++++++++++++ 3 files changed, 268 insertions(+), 4 deletions(-) create mode 100644 tools/gdb/nuttxgdb/protocols/wqueue.py create mode 100644 tools/gdb/nuttxgdb/wqueue.py diff --git a/tools/gdb/nuttxgdb/protocols/wqueue.py b/tools/gdb/nuttxgdb/protocols/wqueue.py new file mode 100644 index 00000000000..479175478df --- /dev/null +++ b/tools/gdb/nuttxgdb/protocols/wqueue.py @@ -0,0 +1,71 @@ +############################################################################ +# tools/gdb/nuttxgdb/protocols/wqueue.py +# +# SPDX-License-Identifier: Apache-2.0 +# +# Licensed to the Apache Software Foundation (ASF) under one or more +# contributor license agreements. See the NOTICE file distributed with +# this work for additional information regarding copyright ownership. The +# ASF licenses this file to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance with the +# License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# +############################################################################ + +from __future__ import annotations + +from typing import List + +from .value import Value + + +class Work(Value): + """struct work_s""" + + class U(Value): + class S(Value): + dq: Value + qtime: Value + + s: S + timer: Value # wdog_s + + u: U + worker: Value # void (*worker_t)(FAR void *arg); + arg: Value + wq: KWorkQueue + + +class KWorker(Value): + """struct kworker_s""" + + pid: Value + work: Value + wait: Value + + +class KWorkQueue(Value): + """struct kwork_wqueue_s""" + + q: Value + sem: Value + exsem: Value + nthreads: int + exit: bool + worker: List[Value] + + +class HPWorkQueue(KWorkQueue): + """struct hp_wqueue_s""" + + +class LPWorkQueue(KWorkQueue): + """struct lp_wqueue_s""" diff --git a/tools/gdb/nuttxgdb/utils.py b/tools/gdb/nuttxgdb/utils.py index fe3f0365a95..2ec248fa644 100644 --- a/tools/gdb/nuttxgdb/utils.py +++ b/tools/gdb/nuttxgdb/utils.py @@ -835,6 +835,31 @@ def get_thread_tls(pid, key): return None +def get_task_argvstr(tcb: Tcb) -> List[str]: + args = [] + try: + TCB_FLAG_TTYPE_MASK = get_symbol_value("TCB_FLAG_TTYPE_MASK") + TCB_FLAG_TTYPE_PTHREAD = get_symbol_value("TCB_FLAG_TTYPE_PTHREAD") + + if tcb.flags & TCB_FLAG_TTYPE_MASK == TCB_FLAG_TTYPE_PTHREAD: + if tcb.type.code != gdb.TYPE_CODE_PTR: + tcb = tcb.address + tcb = tcb.cast(lookup_type("struct pthread_tcb_s").pointer()) + return ["", f"{tcb['cmn']['entry']['main']}", f'{tcb["arg"]}'] + + tls_info_s = lookup_type("struct tls_info_s").pointer() + tls = tcb.stack_alloc_ptr.cast(tls_info_s) + argv = int(tcb.stack_alloc_ptr) + int(tls.tl_size) + argv = gdb.Value(argv).cast(lookup_type("char").pointer().pointer()) + while argv.dereference(): + args.append(argv.dereference().string()) + argv += 1 + except gdb.error: + pass + + return args + + def gather_modules(dir=None) -> List[str]: dir = os.path.normpath(dir) if dir else os.path.dirname(__file__) return [ @@ -931,10 +956,8 @@ class ArrayIterator: raise gdb.error(f"Not an array: {array}, type: {array.type}") if type_code == gdb.TYPE_CODE_ARRAY: - if maxlen is None: - maxlen = nitems(array) - else: - maxlen = min(nitems(array), maxlen) + if n := nitems(array) > 0: + maxlen = min(n, maxlen) if maxlen is not None else n if maxlen is None: raise gdb.error("Need to provide array length.") diff --git a/tools/gdb/nuttxgdb/wqueue.py b/tools/gdb/nuttxgdb/wqueue.py new file mode 100644 index 00000000000..a768411f393 --- /dev/null +++ b/tools/gdb/nuttxgdb/wqueue.py @@ -0,0 +1,170 @@ +############################################################################ +# tools/gdb/nuttxgdb/wqueue.py +# +# SPDX-License-Identifier: Apache-2.0 +# +# Licensed to the Apache Software Foundation (ASF) under one or more +# contributor license agreements. See the NOTICE file distributed with +# this work for additional information regarding copyright ownership. The +# ASF licenses this file to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance with the +# License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# +############################################################################ + +from __future__ import annotations + +from typing import List + +import gdb + +from . import lists, utils +from .protocols import wqueue as p +from .utils import Value + + +class Work(Value, p.Work): + def __init__(self, work: p.Work): + if work.type.code == gdb.TYPE_CODE_PTR: + work = work.dereference() + super().__init__(work) + + @property + def wqueue(self) -> WorkQueue: + return WorkQueue(self.wq) + + def __repr__(self) -> str: + return f"work_s@{self.address:#x}: {self.worker.format_string(styling=True)} arg={self.arg}" + + def __str__(self) -> str: + return self.__repr__() + + +class KWorker(Value, p.KWorker): + """Worker thread information""" + + def __init__(self, worker: p.KWorker, wqueue=None): + if worker.type.code == gdb.TYPE_CODE_PTR: + worker = worker.dereference() + super().__init__(worker) + self.wqueue = wqueue + + @property + def is_running(self): + return self.work + + @property + def work(self) -> Work: + work = self["work"] + return Work(work) if work else None + + @property + def name(self): + return utils.get_task_name(utils.get_tcb(self.pid)) + + def __repr__(self): + return f"kworker_s@{self.address:#x} {self.work or 'idle'}" + + def __str__(self): + return self.__repr__() + + +class WorkQueue(Value, p.KWorkQueue): + """Work queue information""" + + def __init__(self, queue: p.KWorkQueue, name: str = None): + if queue.type.code == gdb.TYPE_CODE_PTR: + queue = queue.dereference() + super().__init__(queue) + self.name = name or "" + + @property + def workers(self) -> List[Work]: + work_s = utils.lookup_type("struct work_s") + return [ + Work(worker.cast(work_s.pointer())) for worker in lists.NxDQueue(self.q) + ] + + @property + def threads(self) -> List[KWorker]: + return [ + KWorker(thread, wqueue=self) + for thread in utils.ArrayIterator(self.worker, self.nthreads) + ] + + @property + def nthreads(self): + return int(self["nthreads"]) + + @property + def is_running(self): + return any(thread.is_running for thread in self.threads) + + @property + def is_exiting(self): + return self.exit + + def __repr__(self): + state = "running" if self.is_running else "idle" + return f"{self.name}@{self.address:#x}, {state}, {self.nthreads} threads, {len(self.workers)} work" + + def __str__(self): + return self.__repr__() + + +def get_work_queues() -> List[WorkQueue]: + entry = gdb.parse_and_eval("work_thread") + kwork_wqueue_s = utils.lookup_type("struct kwork_wqueue_s") + + tcbs = utils.get_tcbs() + # The function address may be or'ed with 0x01 + tcbs = filter(lambda tcb: int(tcb.entry.main) & ~0x01 == entry, tcbs) + queue = [] + for tcb in tcbs: + if not (args := utils.get_task_argvstr(tcb)): + continue + # wqueue = (FAR struct kwork_wqueue_s *) + # ((uintptr_t)strtoul(argv[1], NULL, 16)); + # kworker = (FAR struct kworker_s *) + # ((uintptr_t)strtoul(argv[2], NULL, 16)); + wqueue = gdb.Value(int(args[1], 16)).cast(kwork_wqueue_s.pointer()) + wqueue = WorkQueue(wqueue, name=utils.get_task_name(tcb)) + if wqueue not in queue: + queue.append(wqueue) + + return queue + + +class WorkQueueDump(gdb.Command): + """Show work queue information""" + + def __init__(self): + if not utils.get_symbol_value("CONFIG_SCHED_WORKQUEUE"): + return + + super().__init__("worker", gdb.COMMAND_USER) + + def invoke(self, arg, from_tty): + queues = get_work_queues() + for queue in queues: + print(f"{queue}") + if not queue.is_running: + continue + + print(" Running:") # Dump the work that is running + running = [thread for thread in queue.threads if thread.is_running] + print("\n".join(f" {thread}" for thread in running)) + + if not queue.workers: + continue + + print(" Queued:") + print("\n".join(f" {work}" for work in queue.workers)) -- Gitee From 0891c8d726afd6ff3572662729da5d782ed325e7 Mon Sep 17 00:00:00 2001 From: xuxingliang Date: Sat, 23 Nov 2024 01:54:25 +0800 Subject: [PATCH 022/235] gdb/wdog: add basic wdog dump command VELAPLATFO-47929 (gdb) wdog WDog@0x404864e8: tick: 4294978078 0x402e36b0 arg: 0x40462500 WDog@0x40462ef8: tick: 4294978078 0x402c7900 arg: 0x40462e70 WDog@0x40462d88: tick: 4294978078 0x402c7900 arg: 0x40462d00 WDog@0x4046e488: tick: 4294978079 0x402e36b0 arg: 0x40462440 WDog@0x40462658: tick: 4294978079 0x402c7900 arg: 0x404625d0 (gdb) Change-Id: Iaa0642a5b5890aab3edb998fe604de2f07b2b684 Signed-off-by: xuxingliang --- tools/gdb/nuttxgdb/protocols/wdog.py | 35 +++++++++++++++ tools/gdb/nuttxgdb/wdog.py | 67 ++++++++++++++++++++++++++++ 2 files changed, 102 insertions(+) create mode 100644 tools/gdb/nuttxgdb/protocols/wdog.py create mode 100644 tools/gdb/nuttxgdb/wdog.py diff --git a/tools/gdb/nuttxgdb/protocols/wdog.py b/tools/gdb/nuttxgdb/protocols/wdog.py new file mode 100644 index 00000000000..dc8cecfc665 --- /dev/null +++ b/tools/gdb/nuttxgdb/protocols/wdog.py @@ -0,0 +1,35 @@ +############################################################################ +# tools/gdb/nuttxgdb/protocols/wdog.py +# +# SPDX-License-Identifier: Apache-2.0 +# +# Licensed to the Apache Software Foundation (ASF) under one or more +# contributor license agreements. See the NOTICE file distributed with +# this work for additional information regarding copyright ownership. The +# ASF licenses this file to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance with the +# License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# +############################################################################ + +from __future__ import annotations + +from .value import Value + + +class WDog(Value): + """struct wdog_s""" + + node: Value + arg: Value + func: Value + picbase: Value + expired: Value diff --git a/tools/gdb/nuttxgdb/wdog.py b/tools/gdb/nuttxgdb/wdog.py new file mode 100644 index 00000000000..f25d3c26b65 --- /dev/null +++ b/tools/gdb/nuttxgdb/wdog.py @@ -0,0 +1,67 @@ +############################################################################ +# tools/gdb/nuttxgdb/wdog.py +# +# SPDX-License-Identifier: Apache-2.0 +# +# Licensed to the Apache Software Foundation (ASF) under one or more +# contributor license agreements. See the NOTICE file distributed with +# this work for additional information regarding copyright ownership. The +# ASF licenses this file to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance with the +# License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# +############################################################################ + +from __future__ import annotations + +from typing import List + +import gdb + +from . import lists, utils +from .protocols import wdog as p +from .utils import Value + + +class WDog(Value, p.WDog): + def __init__(self, wdog: p.WDog): + if wdog.type.code == gdb.TYPE_CODE_PTR: + wdog = wdog.dereference() + super().__init__(wdog) + + def __repr__(self) -> str: + return ( + f"WDog@{self.address:#x}: tick: {self.expired: <16}" + f" {self.func.format_string(styling=True)} arg: {self.arg:#x}" + ) + + def __str__(self) -> str: + return self.__repr__() + + +def get_wdog_list() -> List[WDog]: + wdogs = [] + active = utils.parse_and_eval("g_wdactivelist") + for wdog in lists.NxList(active, "struct wdog_s", "node"): + wdogs.append(WDog(wdog)) + + return wdogs + + +class WDogDump(gdb.Command): + """Show wdog timer information""" + + def __init__(self): + super().__init__("wdog", gdb.COMMAND_USER) + + def invoke(self, arg, from_tty): + for wdog in get_wdog_list(): + print(wdog) -- Gitee From 8ed232a2c44469b2e30993d7787bdd5774ca7e63 Mon Sep 17 00:00:00 2001 From: xuxingliang Date: Wed, 13 Nov 2024 11:07:18 +0800 Subject: [PATCH 023/235] gdb/mmleak: add diagnose API to report details of the leak VELAPLATFO-46132 Example of json dump: { "title": "Memory Leak Report", "summary": "Total 105 blks, 22768 bytes leaked", "result": "fail", "command": "mm leak", "data": [ { "count": 1, "pid": 0, "size": 48, "address": 1100447608, "seqno": 0, "alive": true, "backtrace": [] }, { "count": 1, "pid": 4, "size": 368, "address": 1100549056, "seqno": 1041, "alive": false, "backtrace": [ { "address": 1076428472, "function": "", "source": "mm_heap/mm_zalloc.c:45" }, { "address": 1076424018, "function": "", "source": "mm_heap/mm_calloc.c:57" }, { "address": 1076419750, "function": "", "source": "umm_heap/umm_calloc.c:73" }, .... ] }, } Change-Id: I279b76f20c1e0cec4a3200607e9047606e2a684f Signed-off-by: xuxingliang --- tools/gdb/nuttxgdb/memleak.py | 76 ++++++++++++++++++++++++++++------- 1 file changed, 62 insertions(+), 14 deletions(-) diff --git a/tools/gdb/nuttxgdb/memleak.py b/tools/gdb/nuttxgdb/memleak.py index 2a4b2455b62..4c80edd7386 100644 --- a/tools/gdb/nuttxgdb/memleak.py +++ b/tools/gdb/nuttxgdb/memleak.py @@ -22,7 +22,7 @@ import bisect import json import time from os import path -from typing import Dict, Generator, List +from typing import Dict, Generator, List, Tuple import gdb @@ -100,13 +100,9 @@ class MMLeak(gdb.Command): return nodes - def invoke(self, arg: str, from_tty: bool) -> None: - heaps = memdump.get_heaps("g_mmheap") - pids = [int(tcb["pid"]) for tcb in utils.get_tcbs()] - - def is_pid_alive(pid): - return pid in pids - + def collect_leaks( + self, heaps: List[mm.MMHeap] + ) -> Dict[memdump.MMNodeDump, List[memdump.MMNodeDump]]: t = time.time() print("Loading globals from elf...", flush=True, end="") good_nodes = self.global_nodes() # Global memory are all good. @@ -155,15 +151,67 @@ class MMLeak(gdb.Command): print(f" {time.time() - t:.2f}s", flush=True, end="\n") - leak_nodes = memdump.group_nodes(nodes_dict[addr] for addr in sorted_addr) + return memdump.group_nodes((nodes_dict[addr] for addr in sorted_addr)) + + def _iterate_leaks( + self, nodes: Dict[memdump.MMNodeDump, List[memdump.MMNodeDump]] + ) -> Generator[Tuple[memdump.MMNodeDump, bool, int], None, None]: + pids = [int(tcb["pid"]) for tcb in utils.get_tcbs()] + + def is_pid_alive(pid): + return pid in pids + + for node in nodes.keys(): + count = len(nodes[node]) + yield node, is_pid_alive(node.pid), count + + def invoke(self, arg: str, from_tty: bool) -> None: + heaps = memdump.get_heaps("g_mmheap") + + leak_nodes = self.collect_leaks(heaps) memdump.print_header() total_blk = total_size = 0 - for node in leak_nodes.keys(): - count = len(leak_nodes[node]) + for node, alive, count in self._iterate_leaks(leak_nodes): total_blk += count total_size += count * node.nodesize - memdump.print_node( - node, is_pid_alive(node.pid), count=len(leak_nodes[node]) - ) + memdump.print_node(node, alive, count=count) print(f"Leaked {total_blk} blks, {total_size} bytes") + + def diagnose(self, *args, **kwargs): + heaps = memdump.get_heaps("g_mmheap") + leak_nodes = self.collect_leaks(heaps) + total_blk = total_size = 0 + data = [] + for node, alive, count in self._iterate_leaks(leak_nodes): + total_blk += count + total_size += count * node.nodesize + info = { + "count": count, + "pid": node.pid, + "size": node.nodesize, + "address": node.address, + "seqno": node.seqno, + "alive": alive, + "backtrace": [], + } + + if mm.CONFIG_MM_BACKTRACE and node.backtrace and node.backtrace[0]: + bt = utils.Backtrace(node.backtrace) + info["backtrace"] = [ + { + "address": addr, + "function": func, + "source": source, + } + for addr, func, source in bt.backtrace + ] + data.append(info) + + return { + "title": "Memory Leak Report", + "summary": f"Total {total_blk} blks, {total_size} bytes leaked", + "result": "fail" if total_blk else "pass", + "command": "mm leak", + "data": data, + } -- Gitee From 792774bddbf6226607a8ede1ed1ab4ccbd5ae981 Mon Sep 17 00:00:00 2001 From: yinshengkai Date: Tue, 26 Nov 2024 16:38:06 +0800 Subject: [PATCH 024/235] tools: rename tools/gdb/nuttxgdb to tools/pynuttx/nxgdb VELAPLATFO-47018 Signed-off-by: yinshengkai Change-Id: Ic7cd13592c9d021a09ec6e5664f54d0b4e19d9c1 --- tools/gdb/.gitignore | 2 -- tools/pynuttx/.gitignore | 2 ++ tools/{gdb => pynuttx}/gdbinit.py | 8 ++++---- .../{gdb/nuttxgdb => pynuttx/nxgdb}/__init__.py | 4 ++-- tools/{gdb/nuttxgdb => pynuttx/nxgdb}/debug.py | 2 +- .../{gdb/nuttxgdb => pynuttx/nxgdb}/diagnose.py | 2 +- tools/{gdb/nuttxgdb => pynuttx/nxgdb}/dmesg.py | 2 +- tools/{gdb/nuttxgdb => pynuttx/nxgdb}/fs.py | 2 +- tools/{gdb/nuttxgdb => pynuttx/nxgdb}/gcore.py | 2 +- tools/{gdb/nuttxgdb => pynuttx/nxgdb}/libuv.py | 0 tools/{gdb/nuttxgdb => pynuttx/nxgdb}/lists.py | 2 +- tools/{gdb/nuttxgdb => pynuttx/nxgdb}/macros.py | 2 +- .../{gdb/nuttxgdb => pynuttx/nxgdb}/memcheck.py | 2 +- tools/{gdb/nuttxgdb => pynuttx/nxgdb}/memdump.py | 2 +- tools/{gdb/nuttxgdb => pynuttx/nxgdb}/memleak.py | 2 +- tools/{gdb/nuttxgdb => pynuttx/nxgdb}/mm.py | 2 +- tools/{gdb/nuttxgdb => pynuttx/nxgdb}/net.py | 2 +- tools/{gdb/nuttxgdb => pynuttx/nxgdb}/prefix.py | 2 +- tools/{gdb/nuttxgdb => pynuttx/nxgdb}/profile.py | 2 +- .../nuttxgdb => pynuttx/nxgdb}/protocols/fs.py | 2 +- .../nuttxgdb => pynuttx/nxgdb}/protocols/mm.py | 2 +- .../nxgdb}/protocols/thread.py | 2 +- .../nxgdb}/protocols/value.py | 2 +- .../nuttxgdb => pynuttx/nxgdb}/protocols/wdog.py | 2 +- .../nxgdb}/protocols/wqueue.py | 2 +- tools/{gdb/nuttxgdb => pynuttx/nxgdb}/rpmsg.py | 2 +- tools/{gdb/nuttxgdb => pynuttx/nxgdb}/stack.py | 2 +- tools/{gdb/nuttxgdb => pynuttx/nxgdb}/thread.py | 2 +- tools/{gdb/nuttxgdb => pynuttx/nxgdb}/utils.py | 2 +- tools/{gdb/nuttxgdb => pynuttx/nxgdb}/wdog.py | 2 +- tools/{gdb/nuttxgdb => pynuttx/nxgdb}/wqueue.py | 2 +- tools/{gdb => pynuttx}/pyproject.toml | 4 ++-- tools/{gdb => pynuttx}/requirements.txt | 0 tools/{gdb => pynuttx}/tests/run_tests.sh | 2 +- tools/{gdb => pynuttx}/tests/runner.py | 2 +- tools/{gdb => pynuttx}/tests/test_mock_stack.py | 16 ++++++++-------- tools/{gdb => pynuttx}/tests/test_mock_thread.py | 2 +- tools/{gdb => pynuttx}/tests/test_mock_utils.py | 8 ++++---- .../{gdb => pynuttx}/tests/test_runtime_dmesg.py | 2 +- tools/{gdb => pynuttx}/tests/test_runtime_fs.py | 2 +- .../tests/test_runtime_memory.py | 2 +- tools/{gdb => pynuttx}/tests/test_runtime_net.py | 2 +- .../tests/test_runtime_profile.py | 2 +- .../{gdb => pynuttx}/tests/test_runtime_stack.py | 4 ++-- .../tests/test_runtime_thread.py | 4 ++-- 45 files changed, 60 insertions(+), 60 deletions(-) delete mode 100644 tools/gdb/.gitignore create mode 100644 tools/pynuttx/.gitignore rename tools/{gdb => pynuttx}/gdbinit.py (89%) rename tools/{gdb/nuttxgdb => pynuttx/nxgdb}/__init__.py (96%) rename tools/{gdb/nuttxgdb => pynuttx/nxgdb}/debug.py (98%) rename tools/{gdb/nuttxgdb => pynuttx/nxgdb}/diagnose.py (98%) rename tools/{gdb/nuttxgdb => pynuttx/nxgdb}/dmesg.py (98%) rename tools/{gdb/nuttxgdb => pynuttx/nxgdb}/fs.py (99%) rename tools/{gdb/nuttxgdb => pynuttx/nxgdb}/gcore.py (99%) rename tools/{gdb/nuttxgdb => pynuttx/nxgdb}/libuv.py (100%) rename tools/{gdb/nuttxgdb => pynuttx/nxgdb}/lists.py (99%) rename tools/{gdb/nuttxgdb => pynuttx/nxgdb}/macros.py (99%) rename tools/{gdb/nuttxgdb => pynuttx/nxgdb}/memcheck.py (99%) rename tools/{gdb/nuttxgdb => pynuttx/nxgdb}/memdump.py (99%) rename tools/{gdb/nuttxgdb => pynuttx/nxgdb}/memleak.py (99%) rename tools/{gdb/nuttxgdb => pynuttx/nxgdb}/mm.py (99%) rename tools/{gdb/nuttxgdb => pynuttx/nxgdb}/net.py (99%) rename tools/{gdb/nuttxgdb => pynuttx/nxgdb}/prefix.py (97%) rename tools/{gdb/nuttxgdb => pynuttx/nxgdb}/profile.py (98%) rename tools/{gdb/nuttxgdb => pynuttx/nxgdb}/protocols/fs.py (97%) rename tools/{gdb/nuttxgdb => pynuttx/nxgdb}/protocols/mm.py (98%) rename tools/{gdb/nuttxgdb => pynuttx/nxgdb}/protocols/thread.py (98%) rename tools/{gdb/nuttxgdb => pynuttx/nxgdb}/protocols/value.py (98%) rename tools/{gdb/nuttxgdb => pynuttx/nxgdb}/protocols/wdog.py (96%) rename tools/{gdb/nuttxgdb => pynuttx/nxgdb}/protocols/wqueue.py (97%) rename tools/{gdb/nuttxgdb => pynuttx/nxgdb}/rpmsg.py (99%) rename tools/{gdb/nuttxgdb => pynuttx/nxgdb}/stack.py (99%) rename tools/{gdb/nuttxgdb => pynuttx/nxgdb}/thread.py (99%) rename tools/{gdb/nuttxgdb => pynuttx/nxgdb}/utils.py (99%) rename tools/{gdb/nuttxgdb => pynuttx/nxgdb}/wdog.py (98%) rename tools/{gdb/nuttxgdb => pynuttx/nxgdb}/wqueue.py (99%) rename tools/{gdb => pynuttx}/pyproject.toml (92%) rename tools/{gdb => pynuttx}/requirements.txt (100%) rename tools/{gdb => pynuttx}/tests/run_tests.sh (99%) rename tools/{gdb => pynuttx}/tests/runner.py (98%) rename tools/{gdb => pynuttx}/tests/test_mock_stack.py (94%) rename tools/{gdb => pynuttx}/tests/test_mock_thread.py (97%) rename tools/{gdb => pynuttx}/tests/test_mock_utils.py (95%) rename tools/{gdb => pynuttx}/tests/test_runtime_dmesg.py (96%) rename tools/{gdb => pynuttx}/tests/test_runtime_fs.py (97%) rename tools/{gdb => pynuttx}/tests/test_runtime_memory.py (98%) rename tools/{gdb => pynuttx}/tests/test_runtime_net.py (97%) rename tools/{gdb => pynuttx}/tests/test_runtime_profile.py (98%) rename tools/{gdb => pynuttx}/tests/test_runtime_stack.py (94%) rename tools/{gdb => pynuttx}/tests/test_runtime_thread.py (98%) diff --git a/tools/gdb/.gitignore b/tools/gdb/.gitignore deleted file mode 100644 index 12681cb30e7..00000000000 --- a/tools/gdb/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -dist/ -nuttxgdb.egg-info/ diff --git a/tools/pynuttx/.gitignore b/tools/pynuttx/.gitignore new file mode 100644 index 00000000000..1abceb8f415 --- /dev/null +++ b/tools/pynuttx/.gitignore @@ -0,0 +1,2 @@ +dist/ +nxgdb.egg-info/ diff --git a/tools/gdb/gdbinit.py b/tools/pynuttx/gdbinit.py similarity index 89% rename from tools/gdb/gdbinit.py rename to tools/pynuttx/gdbinit.py index 6308e23db7e..556b42808ea 100644 --- a/tools/gdb/gdbinit.py +++ b/tools/pynuttx/gdbinit.py @@ -1,5 +1,5 @@ ############################################################################ -# tools/gdb/gdbinit.py +# tools/pynuttx/gdbinit.py # # Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with @@ -27,9 +27,9 @@ if __name__ == "__main__": if here not in sys.path: sys.path.insert(0, here) - if "nuttxgdb" in sys.modules: + if "nxgdb" in sys.modules: for key in list(sys.modules.keys()): - if key.startswith("nuttxgdb"): + if key.startswith("nxgdb"): del sys.modules[key] - import nuttxgdb # noqa: F401 + import nxgdb # noqa: F401 diff --git a/tools/gdb/nuttxgdb/__init__.py b/tools/pynuttx/nxgdb/__init__.py similarity index 96% rename from tools/gdb/nuttxgdb/__init__.py rename to tools/pynuttx/nxgdb/__init__.py index e8fa48c8056..6f91a91b6ab 100644 --- a/tools/gdb/nuttxgdb/__init__.py +++ b/tools/pynuttx/nxgdb/__init__.py @@ -1,5 +1,5 @@ ############################################################################ -# tools/gdb/nuttxgdb/__init__.py +# tools/pynuttx/nxgdb/__init__.py # # Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with @@ -27,7 +27,7 @@ import gdb if __name__ == "__main__": import sys - gdb.write("Use nuttx/tools/gdb/gdbinit.py instead") + gdb.write("Use nuttx/tools/pynuttx/gdbinit.py instead") sys.exit(1) here = path.dirname(path.abspath(__file__)) diff --git a/tools/gdb/nuttxgdb/debug.py b/tools/pynuttx/nxgdb/debug.py similarity index 98% rename from tools/gdb/nuttxgdb/debug.py rename to tools/pynuttx/nxgdb/debug.py index 5303bd2a163..13b811eaa8a 100644 --- a/tools/gdb/nuttxgdb/debug.py +++ b/tools/pynuttx/nxgdb/debug.py @@ -1,5 +1,5 @@ ############################################################################ -# tools/gdb/nuttxgdb/debug.py +# tools/pynuttx/nxgdb/debug.py # # Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with diff --git a/tools/gdb/nuttxgdb/diagnose.py b/tools/pynuttx/nxgdb/diagnose.py similarity index 98% rename from tools/gdb/nuttxgdb/diagnose.py rename to tools/pynuttx/nxgdb/diagnose.py index e4c8ca0b9f5..7518fc70695 100644 --- a/tools/gdb/nuttxgdb/diagnose.py +++ b/tools/pynuttx/nxgdb/diagnose.py @@ -1,5 +1,5 @@ ############################################################################ -# tools/gdb/nuttxgdb/diagnose.py +# tools/pynuttx/nxgdb/diagnose.py # # Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with diff --git a/tools/gdb/nuttxgdb/dmesg.py b/tools/pynuttx/nxgdb/dmesg.py similarity index 98% rename from tools/gdb/nuttxgdb/dmesg.py rename to tools/pynuttx/nxgdb/dmesg.py index 55da008eded..6db1e4cf199 100644 --- a/tools/gdb/nuttxgdb/dmesg.py +++ b/tools/pynuttx/nxgdb/dmesg.py @@ -1,5 +1,5 @@ ############################################################################ -# tools/gdb/nuttxgdb/dmesg.py +# tools/pynuttx/nxgdb/dmesg.py # # Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with diff --git a/tools/gdb/nuttxgdb/fs.py b/tools/pynuttx/nxgdb/fs.py similarity index 99% rename from tools/gdb/nuttxgdb/fs.py rename to tools/pynuttx/nxgdb/fs.py index 80dacedb670..1f365d29315 100644 --- a/tools/gdb/nuttxgdb/fs.py +++ b/tools/pynuttx/nxgdb/fs.py @@ -1,5 +1,5 @@ ############################################################################ -# tools/gdb/nuttxgdb/fs.py +# tools/pynuttx/nxgdb/fs.py # # Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with diff --git a/tools/gdb/nuttxgdb/gcore.py b/tools/pynuttx/nxgdb/gcore.py similarity index 99% rename from tools/gdb/nuttxgdb/gcore.py rename to tools/pynuttx/nxgdb/gcore.py index 59bc6f67193..93e2e330055 100644 --- a/tools/gdb/nuttxgdb/gcore.py +++ b/tools/pynuttx/nxgdb/gcore.py @@ -1,5 +1,5 @@ ############################################################################ -# tools/gdb/nuttxgdb/gcore.py +# tools/pynuttx/nxgdb/gcore.py # # Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with diff --git a/tools/gdb/nuttxgdb/libuv.py b/tools/pynuttx/nxgdb/libuv.py similarity index 100% rename from tools/gdb/nuttxgdb/libuv.py rename to tools/pynuttx/nxgdb/libuv.py diff --git a/tools/gdb/nuttxgdb/lists.py b/tools/pynuttx/nxgdb/lists.py similarity index 99% rename from tools/gdb/nuttxgdb/lists.py rename to tools/pynuttx/nxgdb/lists.py index 4cec7e81cae..b08e94fb19d 100644 --- a/tools/gdb/nuttxgdb/lists.py +++ b/tools/pynuttx/nxgdb/lists.py @@ -1,5 +1,5 @@ ############################################################################ -# tools/gdb/nuttxgdb/lists.py +# tools/pynuttx/nxgdb/lists.py # # Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with diff --git a/tools/gdb/nuttxgdb/macros.py b/tools/pynuttx/nxgdb/macros.py similarity index 99% rename from tools/gdb/nuttxgdb/macros.py rename to tools/pynuttx/nxgdb/macros.py index b98dc4278df..12564dd9313 100644 --- a/tools/gdb/nuttxgdb/macros.py +++ b/tools/pynuttx/nxgdb/macros.py @@ -1,5 +1,5 @@ ############################################################################ -# tools/gdb/nuttxgdb/macros.py +# tools/pynuttx/nxgdb/macros.py # # Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with diff --git a/tools/gdb/nuttxgdb/memcheck.py b/tools/pynuttx/nxgdb/memcheck.py similarity index 99% rename from tools/gdb/nuttxgdb/memcheck.py rename to tools/pynuttx/nxgdb/memcheck.py index 8f91c002aad..f503729f763 100644 --- a/tools/gdb/nuttxgdb/memcheck.py +++ b/tools/pynuttx/nxgdb/memcheck.py @@ -1,5 +1,5 @@ ############################################################################ -# tools/gdb/nuttxgdb/memcheck.py +# tools/pynuttx/nxgdb/memcheck.py # # Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with diff --git a/tools/gdb/nuttxgdb/memdump.py b/tools/pynuttx/nxgdb/memdump.py similarity index 99% rename from tools/gdb/nuttxgdb/memdump.py rename to tools/pynuttx/nxgdb/memdump.py index aadd72218cf..c16ef04e98a 100644 --- a/tools/gdb/nuttxgdb/memdump.py +++ b/tools/pynuttx/nxgdb/memdump.py @@ -1,5 +1,5 @@ ############################################################################ -# tools/gdb/nuttxgdb/memdump.py +# tools/pynuttx/nxgdb/memdump.py # # Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with diff --git a/tools/gdb/nuttxgdb/memleak.py b/tools/pynuttx/nxgdb/memleak.py similarity index 99% rename from tools/gdb/nuttxgdb/memleak.py rename to tools/pynuttx/nxgdb/memleak.py index 4c80edd7386..45baafb7edb 100644 --- a/tools/gdb/nuttxgdb/memleak.py +++ b/tools/pynuttx/nxgdb/memleak.py @@ -1,5 +1,5 @@ ############################################################################ -# tools/gdb/nuttxgdb/memleak.py +# tools/pynuttx/nxgdb/memleak.py # # Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with diff --git a/tools/gdb/nuttxgdb/mm.py b/tools/pynuttx/nxgdb/mm.py similarity index 99% rename from tools/gdb/nuttxgdb/mm.py rename to tools/pynuttx/nxgdb/mm.py index bb923ecd5e1..ac8cb31bcae 100644 --- a/tools/gdb/nuttxgdb/mm.py +++ b/tools/pynuttx/nxgdb/mm.py @@ -1,5 +1,5 @@ ############################################################################ -# tools/gdb/nuttxgdb/mm.py +# tools/pynuttx/nxgdb/mm.py # # Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with diff --git a/tools/gdb/nuttxgdb/net.py b/tools/pynuttx/nxgdb/net.py similarity index 99% rename from tools/gdb/nuttxgdb/net.py rename to tools/pynuttx/nxgdb/net.py index 9942f5b762b..bc5bf75dc2c 100644 --- a/tools/gdb/nuttxgdb/net.py +++ b/tools/pynuttx/nxgdb/net.py @@ -1,5 +1,5 @@ ############################################################################ -# tools/gdb/nuttxgdb/net.py +# tools/pynuttx/nxgdb/net.py # # Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with diff --git a/tools/gdb/nuttxgdb/prefix.py b/tools/pynuttx/nxgdb/prefix.py similarity index 97% rename from tools/gdb/nuttxgdb/prefix.py rename to tools/pynuttx/nxgdb/prefix.py index 5011392d44b..db1d3923172 100644 --- a/tools/gdb/nuttxgdb/prefix.py +++ b/tools/pynuttx/nxgdb/prefix.py @@ -1,5 +1,5 @@ ############################################################################ -# tools/gdb/nuttxgdb/prefix.py +# tools/pynuttx/nxgdb/prefix.py # # Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with diff --git a/tools/gdb/nuttxgdb/profile.py b/tools/pynuttx/nxgdb/profile.py similarity index 98% rename from tools/gdb/nuttxgdb/profile.py rename to tools/pynuttx/nxgdb/profile.py index 876c4a71247..c691fd6b18a 100644 --- a/tools/gdb/nuttxgdb/profile.py +++ b/tools/pynuttx/nxgdb/profile.py @@ -1,5 +1,5 @@ ############################################################################ -# tools/gdb/nuttxgdb/profile.py +# tools/pynuttx/nxgdb/profile.py # # Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with diff --git a/tools/gdb/nuttxgdb/protocols/fs.py b/tools/pynuttx/nxgdb/protocols/fs.py similarity index 97% rename from tools/gdb/nuttxgdb/protocols/fs.py rename to tools/pynuttx/nxgdb/protocols/fs.py index aa67bb9245e..ae29afa43ef 100644 --- a/tools/gdb/nuttxgdb/protocols/fs.py +++ b/tools/pynuttx/nxgdb/protocols/fs.py @@ -1,5 +1,5 @@ ############################################################################ -# tools/gdb/nuttxgdb/protocols/fs.py +# tools/pynuttx/nxgdb/protocols/fs.py # # Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with diff --git a/tools/gdb/nuttxgdb/protocols/mm.py b/tools/pynuttx/nxgdb/protocols/mm.py similarity index 98% rename from tools/gdb/nuttxgdb/protocols/mm.py rename to tools/pynuttx/nxgdb/protocols/mm.py index e869119b85f..6f3eec59cd2 100644 --- a/tools/gdb/nuttxgdb/protocols/mm.py +++ b/tools/pynuttx/nxgdb/protocols/mm.py @@ -1,5 +1,5 @@ ############################################################################ -# tools/gdb/nuttxgdb/protocols/fs.py +# tools/pynuttx/nxgdb/protocols/fs.py # # Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with diff --git a/tools/gdb/nuttxgdb/protocols/thread.py b/tools/pynuttx/nxgdb/protocols/thread.py similarity index 98% rename from tools/gdb/nuttxgdb/protocols/thread.py rename to tools/pynuttx/nxgdb/protocols/thread.py index 9572b0feaaf..249dd93d010 100644 --- a/tools/gdb/nuttxgdb/protocols/thread.py +++ b/tools/pynuttx/nxgdb/protocols/thread.py @@ -1,5 +1,5 @@ ############################################################################ -# tools/gdb/nuttxgdb/protocols/thread.py +# tools/pynuttx/nxgdb/protocols/thread.py # # Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with diff --git a/tools/gdb/nuttxgdb/protocols/value.py b/tools/pynuttx/nxgdb/protocols/value.py similarity index 98% rename from tools/gdb/nuttxgdb/protocols/value.py rename to tools/pynuttx/nxgdb/protocols/value.py index 6167e5fc8a0..5e733bd28b7 100644 --- a/tools/gdb/nuttxgdb/protocols/value.py +++ b/tools/pynuttx/nxgdb/protocols/value.py @@ -1,5 +1,5 @@ ############################################################################ -# tools/gdb/nuttxgdb/protocols/value.py +# tools/pynuttx/nxgdb/protocols/value.py # # Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with diff --git a/tools/gdb/nuttxgdb/protocols/wdog.py b/tools/pynuttx/nxgdb/protocols/wdog.py similarity index 96% rename from tools/gdb/nuttxgdb/protocols/wdog.py rename to tools/pynuttx/nxgdb/protocols/wdog.py index dc8cecfc665..a8bf968d993 100644 --- a/tools/gdb/nuttxgdb/protocols/wdog.py +++ b/tools/pynuttx/nxgdb/protocols/wdog.py @@ -1,5 +1,5 @@ ############################################################################ -# tools/gdb/nuttxgdb/protocols/wdog.py +# tools/pynuttx/nxgdb/protocols/wdog.py # # SPDX-License-Identifier: Apache-2.0 # diff --git a/tools/gdb/nuttxgdb/protocols/wqueue.py b/tools/pynuttx/nxgdb/protocols/wqueue.py similarity index 97% rename from tools/gdb/nuttxgdb/protocols/wqueue.py rename to tools/pynuttx/nxgdb/protocols/wqueue.py index 479175478df..9c5e5808a58 100644 --- a/tools/gdb/nuttxgdb/protocols/wqueue.py +++ b/tools/pynuttx/nxgdb/protocols/wqueue.py @@ -1,5 +1,5 @@ ############################################################################ -# tools/gdb/nuttxgdb/protocols/wqueue.py +# tools/pynuttx/nxgdb/protocols/wqueue.py # # SPDX-License-Identifier: Apache-2.0 # diff --git a/tools/gdb/nuttxgdb/rpmsg.py b/tools/pynuttx/nxgdb/rpmsg.py similarity index 99% rename from tools/gdb/nuttxgdb/rpmsg.py rename to tools/pynuttx/nxgdb/rpmsg.py index 4bb805c97c3..c19adc4f180 100644 --- a/tools/gdb/nuttxgdb/rpmsg.py +++ b/tools/pynuttx/nxgdb/rpmsg.py @@ -1,5 +1,5 @@ ############################################################################ -# tools/gdb/rpmsg.py +# tools/pynuttx/rpmsg.py # # Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with diff --git a/tools/gdb/nuttxgdb/stack.py b/tools/pynuttx/nxgdb/stack.py similarity index 99% rename from tools/gdb/nuttxgdb/stack.py rename to tools/pynuttx/nxgdb/stack.py index 93073559909..6dd7b782b85 100644 --- a/tools/gdb/nuttxgdb/stack.py +++ b/tools/pynuttx/nxgdb/stack.py @@ -1,5 +1,5 @@ ############################################################################ -# tools/gdb/nuttxgdb/stack.py +# tools/pynuttx/nxgdb/stack.py # # Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with diff --git a/tools/gdb/nuttxgdb/thread.py b/tools/pynuttx/nxgdb/thread.py similarity index 99% rename from tools/gdb/nuttxgdb/thread.py rename to tools/pynuttx/nxgdb/thread.py index a9311223c8e..4fc8ab9d894 100644 --- a/tools/gdb/nuttxgdb/thread.py +++ b/tools/pynuttx/nxgdb/thread.py @@ -1,5 +1,5 @@ ############################################################################ -# tools/gdb/nuttxgdb/thread.py +# tools/pynuttx/nxgdb/thread.py # # Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with diff --git a/tools/gdb/nuttxgdb/utils.py b/tools/pynuttx/nxgdb/utils.py similarity index 99% rename from tools/gdb/nuttxgdb/utils.py rename to tools/pynuttx/nxgdb/utils.py index 2ec248fa644..3a9c6d4f8b1 100644 --- a/tools/gdb/nuttxgdb/utils.py +++ b/tools/pynuttx/nxgdb/utils.py @@ -1,5 +1,5 @@ ############################################################################ -# tools/gdb/nuttxgdb/utils.py +# tools/pynuttx/nxgdb/utils.py # # Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with diff --git a/tools/gdb/nuttxgdb/wdog.py b/tools/pynuttx/nxgdb/wdog.py similarity index 98% rename from tools/gdb/nuttxgdb/wdog.py rename to tools/pynuttx/nxgdb/wdog.py index f25d3c26b65..bd248f82745 100644 --- a/tools/gdb/nuttxgdb/wdog.py +++ b/tools/pynuttx/nxgdb/wdog.py @@ -1,5 +1,5 @@ ############################################################################ -# tools/gdb/nuttxgdb/wdog.py +# tools/pynuttx/nxgdb/wdog.py # # SPDX-License-Identifier: Apache-2.0 # diff --git a/tools/gdb/nuttxgdb/wqueue.py b/tools/pynuttx/nxgdb/wqueue.py similarity index 99% rename from tools/gdb/nuttxgdb/wqueue.py rename to tools/pynuttx/nxgdb/wqueue.py index a768411f393..52abf553a25 100644 --- a/tools/gdb/nuttxgdb/wqueue.py +++ b/tools/pynuttx/nxgdb/wqueue.py @@ -1,5 +1,5 @@ ############################################################################ -# tools/gdb/nuttxgdb/wqueue.py +# tools/pynuttx/nxgdb/wqueue.py # # SPDX-License-Identifier: Apache-2.0 # diff --git a/tools/gdb/pyproject.toml b/tools/pynuttx/pyproject.toml similarity index 92% rename from tools/gdb/pyproject.toml rename to tools/pynuttx/pyproject.toml index b8b271cbd90..d8dc6577236 100644 --- a/tools/gdb/pyproject.toml +++ b/tools/pynuttx/pyproject.toml @@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta" [project] version = "0.0.1" -name = 'nuttxgdb' +name = 'nxgdb' description = 'NuttX RTOS GDB extensions' readme = "README.md" license = { file = 'LICENSE' } @@ -19,4 +19,4 @@ dependencies = ["matplotlib", "numpy", "pyelftools"] requires-python = ">=3.8" [tool.setuptools.package-dir] -nuttxgdb = "nuttxgdb" +nxgdb = "nxgdb" diff --git a/tools/gdb/requirements.txt b/tools/pynuttx/requirements.txt similarity index 100% rename from tools/gdb/requirements.txt rename to tools/pynuttx/requirements.txt diff --git a/tools/gdb/tests/run_tests.sh b/tools/pynuttx/tests/run_tests.sh similarity index 99% rename from tools/gdb/tests/run_tests.sh rename to tools/pynuttx/tests/run_tests.sh index 0bf8f49697b..d3819515aa2 100755 --- a/tools/gdb/tests/run_tests.sh +++ b/tools/pynuttx/tests/run_tests.sh @@ -1,6 +1,6 @@ #! /bin/bash ############################################################################ -# tools/gdb/tests/run_tests.sh +# tools/pynuttx/tests/run_tests.sh # # Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with diff --git a/tools/gdb/tests/runner.py b/tools/pynuttx/tests/runner.py similarity index 98% rename from tools/gdb/tests/runner.py rename to tools/pynuttx/tests/runner.py index 75a7ce89f5b..e5c950c3bf0 100755 --- a/tools/gdb/tests/runner.py +++ b/tools/pynuttx/tests/runner.py @@ -1,6 +1,6 @@ #! /usr/bin/python ############################################################################ -# tools/gdb/tests/runner.py +# tools/pynuttx/tests/runner.py # # Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with diff --git a/tools/gdb/tests/test_mock_stack.py b/tools/pynuttx/tests/test_mock_stack.py similarity index 94% rename from tools/gdb/tests/test_mock_stack.py rename to tools/pynuttx/tests/test_mock_stack.py index 2be141ceaf8..bfbe149eafd 100644 --- a/tools/gdb/tests/test_mock_stack.py +++ b/tools/pynuttx/tests/test_mock_stack.py @@ -1,5 +1,5 @@ ############################################################################ -# tools/gdb/tests/test_mock_stack.py +# tools/pynuttx/tests/test_mock_stack.py # # Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with @@ -22,7 +22,7 @@ import unittest from unittest.mock import MagicMock, patch import gdb -from nuttxgdb.stack import Stack, fetch_stacks +from nxgdb.stack import Stack, fetch_stacks class TestStack(unittest.TestCase): @@ -122,7 +122,7 @@ class TestStack(unittest.TestCase): self.assertTrue("pls check your stack size!" in str(context.exception)) - @patch("nuttxgdb.utils.get_symbol_value") + @patch("nxgdb.utils.get_symbol_value") def test_stack_check_max_usage_no_color(self, mock_utils_get_symbol_value): name = "test_thread" entry = hex(0xABCD) @@ -139,11 +139,11 @@ class TestStack(unittest.TestCase): class TestFetchStacks(unittest.TestCase): - @patch("nuttxgdb.utils.is_target_arch") - @patch("nuttxgdb.utils.in_interrupt_context") - @patch("nuttxgdb.utils.get_register_byname") - @patch("nuttxgdb.utils.get_tcbs") - @patch("nuttxgdb.utils.get_task_name") + @patch("nxgdb.utils.is_target_arch") + @patch("nxgdb.utils.in_interrupt_context") + @patch("nxgdb.utils.get_register_byname") + @patch("nxgdb.utils.get_tcbs") + @patch("nxgdb.utils.get_task_name") def test_fetch_stacks(self, *args): ( mock_get_task_name, diff --git a/tools/gdb/tests/test_mock_thread.py b/tools/pynuttx/tests/test_mock_thread.py similarity index 97% rename from tools/gdb/tests/test_mock_thread.py rename to tools/pynuttx/tests/test_mock_thread.py index c42439332e1..30158b2286f 100644 --- a/tools/gdb/tests/test_mock_thread.py +++ b/tools/pynuttx/tests/test_mock_thread.py @@ -1,5 +1,5 @@ ############################################################################ -# tools/gdb/tests/test_mock_thread.py +# tools/pynuttx/tests/test_mock_thread.py # # Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with diff --git a/tools/gdb/tests/test_mock_utils.py b/tools/pynuttx/tests/test_mock_utils.py similarity index 95% rename from tools/gdb/tests/test_mock_utils.py rename to tools/pynuttx/tests/test_mock_utils.py index 5c391a9a93e..f6e690ed87c 100644 --- a/tools/gdb/tests/test_mock_utils.py +++ b/tools/pynuttx/tests/test_mock_utils.py @@ -1,5 +1,5 @@ ############################################################################ -# tools/gdb/tests/test_mock_utils.py +# tools/pynuttx/tests/test_mock_utils.py # # Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with @@ -22,7 +22,7 @@ import unittest from unittest.mock import MagicMock, patch import gdb -from nuttxgdb import utils +from nxgdb import utils # Loading gdb/__init__.py will append the parent directory to sys.path # Hence we don't need to do importing manually here @@ -110,7 +110,7 @@ class TestIsTargetArch(unittest.TestCase): self.assertTrue(utils.is_target_arch("x86")) self.assertFalse(utils.is_target_arch("arm")) - @patch("nuttxgdb.utils.target_arch", None) + @patch("nxgdb.utils.target_arch", None) def test_is_target_arch_no_attr_architecture_auto(self): del self._mock_frame.architecture @@ -119,7 +119,7 @@ class TestIsTargetArch(unittest.TestCase): ) self.assertTrue(utils.is_target_arch("arm")) - @patch("nuttxgdb.utils.target_arch", None) + @patch("nxgdb.utils.target_arch", None) def test_is_target_arch_no_attr_architecture_specific(self): del self._mock_frame.architecture diff --git a/tools/gdb/tests/test_runtime_dmesg.py b/tools/pynuttx/tests/test_runtime_dmesg.py similarity index 96% rename from tools/gdb/tests/test_runtime_dmesg.py rename to tools/pynuttx/tests/test_runtime_dmesg.py index aae2dd655e8..41383ffe924 100644 --- a/tools/gdb/tests/test_runtime_dmesg.py +++ b/tools/pynuttx/tests/test_runtime_dmesg.py @@ -1,5 +1,5 @@ ############################################################################ -# tools/gdb/tests/test_runtime_dmesg.py +# tools/pynuttx/tests/test_runtime_dmesg.py # # Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with diff --git a/tools/gdb/tests/test_runtime_fs.py b/tools/pynuttx/tests/test_runtime_fs.py similarity index 97% rename from tools/gdb/tests/test_runtime_fs.py rename to tools/pynuttx/tests/test_runtime_fs.py index 1632af32cff..b94a92c01e0 100644 --- a/tools/gdb/tests/test_runtime_fs.py +++ b/tools/pynuttx/tests/test_runtime_fs.py @@ -1,5 +1,5 @@ ############################################################################ -# tools/gdb/tests/test_runtime_fs.py +# tools/pynuttx/tests/test_runtime_fs.py # # Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with diff --git a/tools/gdb/tests/test_runtime_memory.py b/tools/pynuttx/tests/test_runtime_memory.py similarity index 98% rename from tools/gdb/tests/test_runtime_memory.py rename to tools/pynuttx/tests/test_runtime_memory.py index 69b5e550a73..e7a7b4fca0c 100644 --- a/tools/gdb/tests/test_runtime_memory.py +++ b/tools/pynuttx/tests/test_runtime_memory.py @@ -1,5 +1,5 @@ ############################################################################ -# tools/gdb/tests/test_runtime_memory.py +# tools/pynuttx/tests/test_runtime_memory.py # # Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with diff --git a/tools/gdb/tests/test_runtime_net.py b/tools/pynuttx/tests/test_runtime_net.py similarity index 97% rename from tools/gdb/tests/test_runtime_net.py rename to tools/pynuttx/tests/test_runtime_net.py index 9ca8e8e0461..5ad19df5f48 100644 --- a/tools/gdb/tests/test_runtime_net.py +++ b/tools/pynuttx/tests/test_runtime_net.py @@ -1,5 +1,5 @@ ############################################################################ -# tools/gdb/tests/test_runtime_net.py +# tools/pynuttx/tests/test_runtime_net.py # # Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with diff --git a/tools/gdb/tests/test_runtime_profile.py b/tools/pynuttx/tests/test_runtime_profile.py similarity index 98% rename from tools/gdb/tests/test_runtime_profile.py rename to tools/pynuttx/tests/test_runtime_profile.py index d6f405fb26f..172527cfafe 100644 --- a/tools/gdb/tests/test_runtime_profile.py +++ b/tools/pynuttx/tests/test_runtime_profile.py @@ -1,5 +1,5 @@ ############################################################################ -# tools/gdb/tests/test_runtime_profile.py +# tools/pynuttx/tests/test_runtime_profile.py # # Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with diff --git a/tools/gdb/tests/test_runtime_stack.py b/tools/pynuttx/tests/test_runtime_stack.py similarity index 94% rename from tools/gdb/tests/test_runtime_stack.py rename to tools/pynuttx/tests/test_runtime_stack.py index c5accd34f5a..f4d9f49267d 100644 --- a/tools/gdb/tests/test_runtime_stack.py +++ b/tools/pynuttx/tests/test_runtime_stack.py @@ -1,5 +1,5 @@ ############################################################################ -# tools/gdb/tests/test_runtime_stack.py +# tools/pynuttx/tests/test_runtime_stack.py # # SPDX-License-Identifier: Apache-2.0 # @@ -23,7 +23,7 @@ import unittest import gdb -from nuttxgdb.stack import fetch_stacks +from nxgdb.stack import fetch_stacks # The following test cases require running the program as # we need to access the memory of the program diff --git a/tools/gdb/tests/test_runtime_thread.py b/tools/pynuttx/tests/test_runtime_thread.py similarity index 98% rename from tools/gdb/tests/test_runtime_thread.py rename to tools/pynuttx/tests/test_runtime_thread.py index 1356b7b89d3..28a72a4ae72 100644 --- a/tools/gdb/tests/test_runtime_thread.py +++ b/tools/pynuttx/tests/test_runtime_thread.py @@ -1,5 +1,5 @@ ############################################################################ -# tools/gdb/tests/test_runtime_thread.py +# tools/pynuttx/tests/test_runtime_thread.py # # Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with @@ -21,7 +21,7 @@ import unittest import gdb -from nuttxgdb import utils +from nxgdb import utils # The following test cases require running the program as # we need to access the memory of the program -- Gitee From 6d910faabfb76b37015c839de2faedde41c60e9f Mon Sep 17 00:00:00 2001 From: xuxingliang Date: Tue, 26 Nov 2024 09:57:42 +0800 Subject: [PATCH 025/235] nxgdb/fs: use default args VELAPLATFO-43025 Instead of storing it to self Change-Id: I6d11db9b354af9ca002e71b7bd7044c6f736dbaf Signed-off-by: xuxingliang --- tools/pynuttx/nxgdb/fs.py | 33 ++++++++++++++++----------------- 1 file changed, 16 insertions(+), 17 deletions(-) diff --git a/tools/pynuttx/nxgdb/fs.py b/tools/pynuttx/nxgdb/fs.py index 1f365d29315..304cf756aea 100644 --- a/tools/pynuttx/nxgdb/fs.py +++ b/tools/pynuttx/nxgdb/fs.py @@ -303,7 +303,6 @@ class ForeachInode(gdb.Command): def __init__(self): super().__init__("foreach inode", gdb.COMMAND_USER) - self.level = 4096 def get_root_inode(self, addr_or_expr): try: @@ -319,7 +318,7 @@ class ForeachInode(gdb.Command): "-L", "--level", type=int, - default=None, + default=4096, help="Only render the tree to a specific depth", ) parser.add_argument( @@ -333,18 +332,13 @@ class ForeachInode(gdb.Command): args = parser.parse_args(argv) except SystemExit: return None - return { - "level": args.level if args.level else 4096, - "root_inode": ( - self.get_root_inode(args.addr_or_expr) - if args.addr_or_expr - else utils.gdb_eval_or_none("g_root_inode") - ), - } - def print_inode_info(self, node: Inode, level, prefix): - if level > self.level: + return args + + def print_inode_info(self, node: Inode, level=1, prefix="", maxlevel=4096): + if level > maxlevel: return + while node: if node.i_peer: initial_indent = prefix + "├── " @@ -389,7 +383,7 @@ class ForeachInode(gdb.Command): ) ) if node.i_child: - self.print_inode_info(node.i_child, level + 1, newprefix) + self.print_inode_info(node.i_child, level + 1, newprefix, maxlevel) node = node.i_peer def diagnose(self, *args, **kwargs): @@ -404,11 +398,16 @@ class ForeachInode(gdb.Command): } def invoke(self, args, from_tty): - arg = self.parse_arguments(args.split(" ")) - if not arg: + args = self.parse_arguments(args.split(" ")) + if not args: return - self.level = arg["level"] - self.print_inode_info(arg["root_inode"], 1, "") + + root = ( + self.get_root_inode(args.addr_or_expr) + if args.addr_or_expr + else utils.gdb_eval_or_none("g_root_inode") + ) + self.print_inode_info(root, maxlevel=args.level) class InfoShmfs(gdb.Command): -- Gitee From 9c7265bfd19618528d18f4b078292c3b749ea016 Mon Sep 17 00:00:00 2001 From: xuxingliang Date: Tue, 26 Nov 2024 11:00:26 +0800 Subject: [PATCH 026/235] nxgdb/fs: simplify inode print and add more options MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit VELAPLATFO-43025 Use Inode.__repr__ for print and use single line for all information. Add 'verbose' and 'nodetype' option to show more details and only print specifiy node type like PIPE. Add / to name for pseudodir. Catch memory error when accessing node element. E.g. (gdb) foreach inode --nodetype pipe ├── run/ 0x41a27a50 PSEUDODIR │ ├── bt:bluetoothCS1fd26 0x4530c510 PIPE │ ├── bt:bluetoothCS20 0x42daae40 PIPE │ ├── socketpair0x457fd2e0SC20540 0x44ea27b0 PIPE │ └── tmp/ 0x42dd7cf0 PSEUDODIR │ │ └── usock/ 0x42dd6c10 PSEUDODIR │ │ └── speech.usockHD 0x42dc8270 PIPE │ ├── central_lite.socketCS5e 0x42e1e7b0 PIPE │ ├── central_service_lite.socketSC86 0x432ee6d0 PIPE │ │ └── usock/ 0x43d6ed60 PSEUDODIR │ │ └── speech.usockHD 0x43da2ba0 PIPE │ ├── uv-feature-sockSC8d 0x43540430 PIPE │ ├── uv-miot-sockCS54 0x42e272e0 PIPE │ └── uv-miot-sockSC54 0x42e270b0 PIPE Change-Id: Ief03c8ea591d0e6a8ccda5f6aa4457a9b21b91e4 Signed-off-by: xuxingliang --- tools/pynuttx/nxgdb/fs.py | 197 +++++++++++++++---------- tools/pynuttx/tests/test_runtime_fs.py | 2 +- 2 files changed, 118 insertions(+), 81 deletions(-) diff --git a/tools/pynuttx/nxgdb/fs.py b/tools/pynuttx/nxgdb/fs.py index 304cf756aea..a351e7111cb 100644 --- a/tools/pynuttx/nxgdb/fs.py +++ b/tools/pynuttx/nxgdb/fs.py @@ -25,7 +25,7 @@ from typing import Generator, Tuple import gdb from . import utils -from .protocols.fs import File, Inode +from .protocols import fs as p from .protocols.thread import Tcb FSNODEFLAG_TYPE_MASK = utils.get_symbol_value("FSNODEFLAG_TYPE_MASK") @@ -70,55 +70,91 @@ class InodeType(enum.Enum): UNKNOWN = 12 -def get_inode_name(inode: Inode): - if not inode: - return "" - - def special_inode_name(inode): - global g_special_inodes - if not g_special_inodes: - g_special_inodes = {} - for special in ( - "perf", - "timerfd", - "signalfd", - "dir", - "inotify", - "epoll", - "eventfd", - "sock", - ): - value = utils.gdb_eval_or_none(f"g_{special}_inode") - if value: - g_special_inodes[special] = value.address +class Inode(utils.Value, p.Inode): + def __init__(self, obj: gdb.Value | utils.Value): + super().__init__(obj) - for name, value in g_special_inodes.items(): - if value == inode: - return name + def __str__(self) -> str: + name = get_inode_name(self) + type = inode_gettype(self) + return f"{name}{'/' if type == InodeType.PSEUDODIR else ''}{int(self): #x} {type.name}" - return None + def __repr__(self) -> str: + return self.__str__() - if name := special_inode_name(inode): - return name + def details(self) -> str: + details = ( + f"ino: {self.i_ino}, crefs: {self.i_crefs}" + f", flags: {self.i_flags}, private: {self.i_private}" + ) + + if CONFIG_PSEUDOFS_FILE: + details += f", i_size: {self.i_size}" + if CONFIG_PSEUDOFS_ATTRIBUTES: + details += f", i_mode: {self.i_mode}, i_owner: {self.i_owner}, i_group: {self.i_group}" + details += f", i_atime: {self.i_atime}, i_mtime: {self.i_mtime}, i_ctime: {self.i_ctime}" + return details + + @property + def nodetype(self) -> InodeType: + return inode_gettype(self) + + +def get_inode_name(inode: p.Inode): + try: + if not inode: + return "" + + def special_inode_name(inode): + global g_special_inodes + if not g_special_inodes: + g_special_inodes = {} + for special in ( + "perf", + "timerfd", + "signalfd", + "dir", + "inotify", + "epoll", + "eventfd", + "sock", + ): + value = utils.gdb_eval_or_none(f"g_{special}_inode") + if value: + g_special_inodes[special] = value.address + + for name, value in g_special_inodes.items(): + if value == inode: + return name + + return None - ptr = inode.i_name.cast(gdb.lookup_type("char").pointer()) - return ptr.string() + if name := special_inode_name(inode): + return name + ptr = inode.i_name.cast(gdb.lookup_type("char").pointer()) + return ptr.string() + except gdb.MemoryError: + return "" -def inode_getpath(inode: Inode): + +def inode_getpath(inode: p.Inode): """get path fron inode""" - if not inode: - return "" + try: + if not inode: + return "" - name = get_inode_name(inode) + name = get_inode_name(inode) - if inode.i_parent: - return inode_getpath(inode.i_parent) + "/" + name + if inode.i_parent: + return inode_getpath(inode.i_parent) + "/" + name - return name + return name + except gdb.MemoryError: + return "" -def inode_gettype(inode: Inode) -> InodeType: +def inode_gettype(inode: p.Inode) -> InodeType: if not inode: return InodeType.UNKNOWN @@ -146,8 +182,8 @@ def get_file(tcb: Tcb, fd): return fl_files[row][col] -def foreach_inode(root=None, path="") -> Generator[Tuple[Inode, str], None, None]: - node: Inode = root or utils.parse_and_eval("g_root_inode").i_child +def foreach_inode(root=None, path="") -> Generator[Tuple[p.Inode, str], None, None]: + node: p.Inode = root or utils.parse_and_eval("g_root_inode").i_child while node: newpath = path + "/" + get_inode_name(node) yield node, newpath @@ -182,7 +218,7 @@ class Fdinfo(gdb.Command): super().__init__("fdinfo", gdb.COMMAND_DATA, gdb.COMPLETE_EXPRESSION) self.total_fd_count = 0 - def print_file_info(self, fd, file: File, formatter: str): + def print_file_info(self, fd, file: p.File, formatter: str): backtrace_formatter = "{0:<5} {1:<36} {2}" oflags = int(file.f_oflags) @@ -321,6 +357,19 @@ class ForeachInode(gdb.Command): default=4096, help="Only render the tree to a specific depth", ) + parser.add_argument( + "--nodetype", + type=str, + choices=[e.name.lower() for e in InodeType], + default=None, + help="Only show the specific type of inode", + ) + parser.add_argument( + "-v", + "--verbose", + action="store_true", + help="Show more information", + ) parser.add_argument( "addr_or_expr", type=str, @@ -328,6 +377,7 @@ class ForeachInode(gdb.Command): default=None, help="set the start inode to be tranversed", ) + try: args = parser.parse_args(argv) except SystemExit: @@ -335,56 +385,34 @@ class ForeachInode(gdb.Command): return args - def print_inode_info(self, node: Inode, level=1, prefix="", maxlevel=4096): + def print_inode_info( + self, node: Inode, level=1, prefix="", maxlevel=4096, type=None, verbose=False + ): if level > maxlevel: return while node: if node.i_peer: initial_indent = prefix + "├── " - subsequent_indent = prefix + "│ " newprefix = prefix + "│ " else: initial_indent = prefix + "└── " - subsequent_indent = prefix + " " newprefix = prefix + " " - gdb.write( - "%s [%s], %s, %s\n" - % (initial_indent, get_inode_name(node), node.i_ino, node) - ) - gdb.write( - "%s i_crefs: %s, i_flags: %s, i_private: %s\n" - % ( - subsequent_indent, - node.i_crefs, - node.i_flags, - node.i_private, - ) - ) - if CONFIG_PSEUDOFS_FILE: - gdb.write("%s i_size: %s\n" % (subsequent_indent, node.i_size)) - if CONFIG_PSEUDOFS_ATTRIBUTES: - gdb.write( - "%s i_mode: %s, i_owner: %s, i_group: %s\n" - % ( - subsequent_indent, - node.i_mode, - node.i_owner, - node.i_group, - ) - ) + + if ( + not type + or node.nodetype == type + or any(n.i_parent == node for n, _ in self.nodes) + ): gdb.write( - "%s i_atime: %s, i_mtime: %s, i_ctime: %s\n" - % ( - subsequent_indent, - node.i_atime, - node.i_mtime, - node.i_ctime, - ) + f"{initial_indent}{node} {node.details() if verbose else ''}\n" ) + if node.i_child: - self.print_inode_info(node.i_child, level + 1, newprefix, maxlevel) - node = node.i_peer + self.print_inode_info( + Inode(node.i_child), level + 1, newprefix, maxlevel, type, verbose + ) + node = Inode(node.i_peer) def diagnose(self, *args, **kwargs): output = gdb.execute("foreach inode", to_string=True) @@ -407,7 +435,16 @@ class ForeachInode(gdb.Command): if args.addr_or_expr else utils.gdb_eval_or_none("g_root_inode") ) - self.print_inode_info(root, maxlevel=args.level) + + nodetype = InodeType[args.nodetype.upper()] if args.nodetype else None + if nodetype: + self.nodes = list( + filter(lambda x: inode_gettype(x[0]) == nodetype, foreach_inode(root)) + ) + + self.print_inode_info( + Inode(root), maxlevel=args.level, type=nodetype, verbose=args.verbose + ) class InfoShmfs(gdb.Command): @@ -419,7 +456,7 @@ class InfoShmfs(gdb.Command): self.total_size = 0 self.block_count = 0 - def shm_filter(self, node: Inode, path): + def shm_filter(self, node: p.Inode, path): if inode_gettype(node) != InodeType.SHM: return diff --git a/tools/pynuttx/tests/test_runtime_fs.py b/tools/pynuttx/tests/test_runtime_fs.py index b94a92c01e0..b1b4139aff1 100644 --- a/tools/pynuttx/tests/test_runtime_fs.py +++ b/tools/pynuttx/tests/test_runtime_fs.py @@ -49,7 +49,7 @@ class TestFs(unittest.TestCase): def test_foreach_inode(self): out = gdb.execute("foreach inode", to_string=True) - self.check_output(out, expect="[console],") + self.check_output(out, expect=" console ") def test_foreach_inode_addr(self): pass -- Gitee From 033f9b7eed51776cc2c9828a003cbb1400e9157f Mon Sep 17 00:00:00 2001 From: xuxingliang Date: Tue, 26 Nov 2024 14:09:49 +0800 Subject: [PATCH 027/235] nxgdb/circbuf: add command to dump circbuf data VELAPLATFO-48253 Dump the basic information of a circle buffer, optionally dump the history data it contains. Print with easy to read data type. `--unread` is to dump all data that hasn't been read. E.g. (gdb) circbuf 0x61c90340 --type "struct touch_sample_s" --history (struct circbuf_s *)0x61c90340 base: 0x61c902f0 size: 64 head: 5312 tail: 5248 Dumping history data with type struct touch_sample_s 0: struct touch_sample_s {npoints = 1, point = {{id = 0 '\000', flags = 26 '\032', x = 277, y = 311, h = 0, w = 0, gesture = 255, pressure = 0, timestamp = 157856200}}} 1: struct touch_sample_s {npoints = 1, point = {{id = 0 '\000', flags = 28 '\034', x = 277, y = 311, h = 0, w = 0, gesture = 255, pressure = 0, timestamp = 157872000}}} (gdb) Note the way I find 0x61c90340 is a circle buffer is through below steps. 1. Use fdinfo to dump all the fd and notice the filep associated with /dev/inputN device. 2. print the content of filep: `p *(struct file *)0x61c8c0c0` 3. Check nuttx/drivers/input/touchscreen_upper.c we can see the type of filep->f_priv is struct touch_openpriv_s *, print it 4. `p *(struct touch_openpriv_s *)0x61c90340` 5. circbuf is at offset 0 of touch_openpriv_s struct. Use `p &((struct touch_openpriv_s *)0x61c90340)->circbuf` also works. Change-Id: I4be0dc13de1f1e3c45bcca8324dab7915a1ed4a6 Signed-off-by: xuxingliang --- tools/pynuttx/nxgdb/circbuf.py | 195 +++++++++++++++++++++++ tools/pynuttx/nxgdb/protocols/circbuf.py | 35 ++++ 2 files changed, 230 insertions(+) create mode 100644 tools/pynuttx/nxgdb/circbuf.py create mode 100644 tools/pynuttx/nxgdb/protocols/circbuf.py diff --git a/tools/pynuttx/nxgdb/circbuf.py b/tools/pynuttx/nxgdb/circbuf.py new file mode 100644 index 00000000000..3f0750ba4a7 --- /dev/null +++ b/tools/pynuttx/nxgdb/circbuf.py @@ -0,0 +1,195 @@ +############################################################################ +# tools/pynuttx/nxgdb/circbuf.py +# +# SPDX-License-Identifier: Apache-2.0 +# +# Licensed to the Apache Software Foundation (ASF) under one or more +# contributor license agreements. See the NOTICE file distributed with +# this work for additional information regarding copyright ownership. The +# ASF licenses this file to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance with the +# License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# +############################################################################ + +import argparse +from typing import Generator + +import gdb + +from . import utils +from .protocols import circbuf as p + + +class CircBuf(utils.Value, p.CircBuf): + def __init__( + self, obj: gdb.Value | utils.Value, datatype: gdb.Type | None = None + ) -> None: + circbuf_s = utils.lookup_type("struct circbuf_s") + if obj.type.code == gdb.TYPE_CODE_INT: + obj = obj.cast(circbuf_s.pointer()) + + if obj.type.code == gdb.TYPE_CODE_PTR: + obj.cast(circbuf_s.pointer()) + obj = obj.dereference() + + super().__init__(obj) + + # datatype must not be a pointer, because we are going to construct value from memory + if not datatype: + datatype = utils.lookup_type("char") + + if isinstance(datatype, str): + datatype = utils.lookup_type(datatype) + + if datatype.code == gdb.TYPE_CODE_PTR: + datatype = datatype.target() + + self.datatype = datatype + + def __str__(self) -> str: + return ( + f"(struct circbuf_s *){hex(self.address)} base: {self.base} " + f"size: {self.size} head: {self.head} tail: {self.tail}" + ) + + @property + def size(self) -> int: + return int(self["size"]) + + @property + def used(self) -> int: + return int(self["head"]) - int(self["tail"]) + + @property + def space(self) -> int: + return self.size - self.used + + @property + def is_inited(self) -> bool: + return bool(self["base"]) + + @property + def is_empty(self) -> bool: + return self.used == 0 + + @property + def is_full(self) -> bool: + return not self.space + + def _peekat(self, pos, len) -> memoryview: + if len > self.size: + return None + + pos = pos % self.size + total = len + if pos + len > self.size: + len = self.size - pos + + memory = gdb.selected_inferior().read_memory(self.base + pos, len) + if len < total: + memory += gdb.selected_inferior().read_memory(self.base, total - len) + return memory + + @property + def history(self) -> Generator[utils.Value, None, None]: + """Iterate over the history data in the circbuf_s, from oldest to newest""" + if not self.base or not self.size: + # Uninitialized buffer + return [] + + head = int(self.head) + size = int(self.size) + sizeof = self.datatype.sizeof + + if head < size: + # The buffer is never wrapped, read from the beginning + offset = 0 + end = head + else: + # The buffer is wrapped, read from the head + offset = head % size + end = offset + size + + while offset < end: + memory = self._peekat(offset, sizeof) + value = gdb.Value(memory, self.datatype) + yield value + offset += sizeof + + @property + def unread(self) -> Generator[utils.Value, None, None]: + """Return all unread data in circle buffer""" + if not self.base or not self.size: + return [] + + # Read from tail towards head for all data. + tail = int(self.tail) + head = int(self.head) + sizeof = self.datatype.sizeof + offset = tail + while offset < head: + memory = self._peekat(offset, sizeof) + yield gdb.Value(memory, self.datatype) + offset += sizeof + + +class CircBufInfo(gdb.Command): + """Print circbuf_s information""" + + def __init__(self): + super().__init__("circbuf", gdb.COMMAND_USER) + + def invoke(self, arg: str, from_tty: bool) -> None: + parser = argparse.ArgumentParser(description="Dump circle buffer information") + parser.add_argument( + "--type", + type=str, + help="The data type the circbuf_s contains", + default=None, + ) + parser.add_argument( + "--history", + action="store_true", + help="Dump the history data in the circbuf_s", + ) + parser.add_argument( + "--unread", + action="store_true", + help="Dump the unread data in the circbuf_s", + ) + parser.add_argument( + "address", + type=str, + help="The address of the circubuf_s", + ) + + try: + args = parser.parse_args(gdb.string_to_argv(arg)) + except SystemExit: + gdb.write("Invalid arguments\n") + return + + entry = utils.parse_and_eval(args.address) + circbuf = CircBuf(entry, datatype=args.type) + + print(circbuf) # Dump buffer basic information + + if args.history: + dumpdata = circbuf.history + elif args.unread: + dumpdata = circbuf.unread + else: + dumpdata = [] + + print(f"Dumping data with type {args.type}") + for i, data in enumerate(dumpdata): + print(f"{i}: {data.format_string(styling=True)}") diff --git a/tools/pynuttx/nxgdb/protocols/circbuf.py b/tools/pynuttx/nxgdb/protocols/circbuf.py new file mode 100644 index 00000000000..85b3b688191 --- /dev/null +++ b/tools/pynuttx/nxgdb/protocols/circbuf.py @@ -0,0 +1,35 @@ +############################################################################ +# tools/pynuttx/nxgdb/protocols/circbuf.py +# +# SPDX-License-Identifier: Apache-2.0 +# +# Licensed to the Apache Software Foundation (ASF) under one or more +# contributor license agreements. See the NOTICE file distributed with +# this work for additional information regarding copyright ownership. The +# ASF licenses this file to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance with the +# License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# +############################################################################ + +from __future__ import annotations + +from .value import Value + + +class CircBuf(Value): + """struct circbuf_s""" + + base: Value + size: Value + head: Value + tail: Value + external: Value -- Gitee From e24129b92592b71aa59504aa9b94dd434c65e1d4 Mon Sep 17 00:00:00 2001 From: xuxingliang Date: Mon, 25 Nov 2024 09:17:16 +0800 Subject: [PATCH 028/235] nxgdb/uorb: add basic uorb topic dump VELAPLATFO-48256 (gdb) uorb Address Topic Subs Ads esize nbuf latency interval Circbuf 0x41a475c0 bt_stack_state 1 1 16 1 0 4294967295 0x41a475f8 0x42d831a0 screen_onoff 1 0 16 1 0 4294967295 0x42d831d8 0x419a5510 sensor_light 0 1 16 1 0 4294967295 0x419a5548 (gdb) With the circbuf address, we can dump the data further. E.g. (struct circbuf_s *)0x41a475f8 base: 0x44687ba0 size: 16 head: 672 tail: 656 Dumping data with type struct bt_stack_state 0: {timestamp = 56504175, state = BT_STACK_STATE_OFF} (gdb) Change-Id: I76895ba3887071672ad7998897b0a6696ccce690 Signed-off-by: xuxingliang --- tools/pynuttx/nxgdb/protocols/uorb.py | 103 +++++++++++++++++ tools/pynuttx/nxgdb/uorb.py | 158 ++++++++++++++++++++++++++ 2 files changed, 261 insertions(+) create mode 100644 tools/pynuttx/nxgdb/protocols/uorb.py create mode 100644 tools/pynuttx/nxgdb/uorb.py diff --git a/tools/pynuttx/nxgdb/protocols/uorb.py b/tools/pynuttx/nxgdb/protocols/uorb.py new file mode 100644 index 00000000000..49740a6e7e0 --- /dev/null +++ b/tools/pynuttx/nxgdb/protocols/uorb.py @@ -0,0 +1,103 @@ +############################################################################ +# tools/pynuttx/nxgdb/protocols/uorb.py +# +# SPDX-License-Identifier: Apache-2.0 +# +# Licensed to the Apache Software Foundation (ASF) under one or more +# contributor license agreements. See the NOTICE file distributed with +# this work for additional information regarding copyright ownership. The +# ASF licenses this file to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance with the +# License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# +############################################################################ + +from __future__ import annotations + +from .value import Value + + +class OrbMetadata(Value): + """struct orb_metadata_s""" + + o_name: Value + o_size: Value + o_format: Value + + +class SensorMeta(Value): + """struct sensor_meta_s""" + + esize: Value + name: Value + + +class SensorState(Value): + """struct sensor_state_s""" + + esize: Value + nbuffer: Value + min_latency: Value + min_interval: Value + nsubscribers: Value + nadvertisers: Value + generation: Value + priv: Value + + +class SensorUState(Value): + """struct sensor_ustate_s""" + + esize: Value + latency: Value + interval: Value + generation: Value + + +class SensorUpper(Value): + """struct sensor_upperhalf_s""" + + lower: Value + state: SensorState + timing: Value + buffer: Value + lock: Value + userlist: Value + + +class SensorLower(Value): + """struct sensor_lowerhalf_s""" + + type: Value + nbuffer: Value + uncalibrated: Value + ops: Value + push_event: Value + notify_event: Value + + sensor_lock: Value + sensor_unlock: Value + priv: Value + persist: Value + + +class SensorUser(Value): + """struct sensor_user_s""" + + node: Value + fds: Value + role: Value + changed: Value + event: Value + flushing: Value + buffersem: Value + bufferpos: Value + state: SensorUState diff --git a/tools/pynuttx/nxgdb/uorb.py b/tools/pynuttx/nxgdb/uorb.py new file mode 100644 index 00000000000..3e0c611edbc --- /dev/null +++ b/tools/pynuttx/nxgdb/uorb.py @@ -0,0 +1,158 @@ +############################################################################ +# tools/pynuttx/nxgdb/uorb.py +# +# SPDX-License-Identifier: Apache-2.0 +# +# Licensed to the Apache Software Foundation (ASF) under one or more +# contributor license agreements. See the NOTICE file distributed with +# this work for additional information regarding copyright ownership. The +# ASF licenses this file to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance with the +# License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# +############################################################################ + +from __future__ import annotations + +import argparse +import re +from typing import List + +import gdb + +from . import fs, utils +from .circbuf import CircBuf +from .protocols import uorb as p + + +class Sensor(utils.Value, p.SensorUpper): + """struct sensor_upperhalf_s and enhancement""" + + inode_s = utils.lookup_type("struct inode") + sensor_upperhalf_s = utils.lookup_type("struct sensor_upperhalf_s") + + def __init__(self, inode: gdb.Value | utils.Value, path=None): + # inode must be type of struct inode * + if inode.type.code != gdb.TYPE_CODE_PTR: + raise ValueError(f"Expect pointer type, got {inode.type}") + + super().__init__(inode["i_private"].cast(self.sensor_upperhalf_s.pointer())) + self.inode = inode + self._path = path + + def __repr__(self) -> str: + state = self.state + return f"{hex(self)} {self.topicname} {state.nsubscribers} subscribers, {state.nadvertisers} advertisers" + + def details(self) -> str: + state = self.state + return f"nbuffer: {state.nbuffer}, latency: {state.min_latency}, interval: {state.min_interval}" + + def __str__(self) -> str: + return self.__repr__() + + @property + def path(self): + return self._path or fs.inode_getpath(self.inode) + + @property + def nsubscribers(self) -> int: + return int(self.state["nsubscribers"]) + + @property + def nadvertisers(self) -> int: + return int(self.state["nadvertisers"]) + + @property + def topicname(self): + name = self.path.split("/")[-1] + name = re.sub(r"(\d$)", "", name) + name = re.sub(r"(_uncal$)", "", name) + return name + + @property + def metadata(self) -> p.OrbMetadata: + return utils.gdb_eval_or_none(f"g_orb_{self.topicname}") + + @property + def datatype(self) -> gdb.Type: + """Return the datatype of the topic like struct sensor_accel""" + return utils.lookup_type(f"struct {self.topicname}") + + @property + def circbuf(self) -> CircBuf: + if not self.datatype: + return None + return CircBuf(self.buffer, datatype=self.datatype.pointer()) + + +def get_topic_inodes(topic: str = None) -> List[fs.Inode]: + nodes = ( + (node, path) + for node, path in fs.foreach_inode() + if path.startswith("/dev/uorb/") and (not topic or topic in path) + ) + return nodes + + +def get_topics(topic: str = None) -> List[Sensor]: + nodes = get_topic_inodes(topic) + return (Sensor(node, path=path) for node, path in nodes) + + +class uORBDump(gdb.Command): + """Dump uORB topics""" + + formatter = "{:<20} {:<24} {:<6} {:<6} {:<6} {:<6} {:<12} {:<12} {:<20}" + header = ( + "Address", + "Topic", + "Subs", + "Ads", + "esize", + "nbuf", + "latency", + "interval", + "Circbuf", + ) + + def __init__(self): + super().__init__("uorb", gdb.COMMAND_USER) + + def invoke(self, arg: str, from_tty: bool) -> None: + parser = argparse.ArgumentParser(description=self.__doc__) + parser.add_argument( + "--topic", + type=str, + help="The topic name to dump, e.g. 'sensor_accel'", + default=None, + ) + + try: + args = parser.parse_args(gdb.string_to_argv(arg)) + except SystemExit: + return + + print(self.formatter.format(*self.header)) + for topic in get_topics(topic=args.topic): + print( + self.formatter.format( + hex(topic), + topic.topicname, + topic.nsubscribers, + topic.nadvertisers, + topic.state.esize, + topic.state.nbuffer, + topic.state.min_latency, + topic.state.min_interval, + hex(topic.buffer.address), + ) + ) -- Gitee From 47c8361dcb3018570f269c1b5f3c731b8ff98f3d Mon Sep 17 00:00:00 2001 From: xuxingliang Date: Wed, 27 Nov 2024 11:30:27 +0800 Subject: [PATCH 029/235] nxgdb/utils: add getfield and fix ArrayIterator VELAPLATFO-48413 Change-Id: Ie1cbcf82b00fde52265e8c56bef46b67a2edee37 Signed-off-by: xuxingliang --- tools/pynuttx/nxgdb/utils.py | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/tools/pynuttx/nxgdb/utils.py b/tools/pynuttx/nxgdb/utils.py index 3a9c6d4f8b1..6eb1dfea4ad 100644 --- a/tools/pynuttx/nxgdb/utils.py +++ b/tools/pynuttx/nxgdb/utils.py @@ -439,6 +439,20 @@ def get_field(val, key, default=None): return default +def has_field(obj: Union[gdb.Type, gdb.Value], key): + if isinstance(obj, gdb.Type): + t = obj + elif isinstance(obj, gdb.Value): + t = obj.type + else: + raise gdb.GdbError(f"Unsupported type {type(obj)}") + + while t.code in (gdb.TYPE_CODE_PTR, gdb.TYPE_CODE_ARRAY, gdb.TYPE_CODE_TYPEDEF): + t = t.target() + + return any(f.name == key for f in t.fields()) + + def get_bytes(val, size): """Convert a gdb value to a bytes object""" try: @@ -956,7 +970,7 @@ class ArrayIterator: raise gdb.error(f"Not an array: {array}, type: {array.type}") if type_code == gdb.TYPE_CODE_ARRAY: - if n := nitems(array) > 0: + if (n := nitems(array)) > 0: maxlen = min(n, maxlen) if maxlen is not None else n if maxlen is None: -- Gitee From 04aeb1460ecb1aa44425b06f1f45ba591960f701 Mon Sep 17 00:00:00 2001 From: xuxingliang Date: Wed, 27 Nov 2024 11:29:49 +0800 Subject: [PATCH 030/235] nxgdb/irq: add irqinfo command VELAPLATFO-48413 (gdb) irqinfo IRQ COUNT TIME RATE HANDLER ARGUMENT 0 0 0 N/A mps_reserved 0x0 2 0 0 N/A mps_nmi 0x0 3 0 0 N/A arm_hardfault 0x0 4 0 0 N/A arm_memfault 0x0 5 0 0 N/A arm_busfault 0x0 6 0 0 N/A arm_usagefault 0x0 11 1 0 N/A arm_svcall 0x0 12 0 0 N/A arm_dbgmonitor 0x0 14 0 0 N/A mps_pendsv 0x0 15 6581421 0 N/A systick_interrupt 0x100010c 49 2 0 N/A uart_cmsdk_tx_interrupt 0x1000010 50 0 0 N/A uart_cmsdk_rx_interrupt 0x1000010 59 2 0 N/A uart_cmsdk_ov_interrupt 0x1000010 (gdb) Change-Id: I8949dcd7b1284c799e9e6759420181defe34d654 Signed-off-by: xuxingliang --- tools/pynuttx/nxgdb/irq.py | 80 ++++++++++++++++++++++++++++ tools/pynuttx/nxgdb/protocols/irq.py | 35 ++++++++++++ 2 files changed, 115 insertions(+) create mode 100644 tools/pynuttx/nxgdb/irq.py create mode 100644 tools/pynuttx/nxgdb/protocols/irq.py diff --git a/tools/pynuttx/nxgdb/irq.py b/tools/pynuttx/nxgdb/irq.py new file mode 100644 index 00000000000..5a36a72efc3 --- /dev/null +++ b/tools/pynuttx/nxgdb/irq.py @@ -0,0 +1,80 @@ +############################################################################ +# tools/pynuttx/nxgdb/irq.py +# +# SPDX-License-Identifier: Apache-2.0 +# +# Licensed to the Apache Software Foundation (ASF) under one or more +# contributor license agreements. See the NOTICE file distributed with +# this work for additional information regarding copyright ownership. The +# ASF licenses this file to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance with the +# License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# +############################################################################ + +from __future__ import annotations + +from typing import List + +import gdb + +from . import utils +from .protocols import irq as p + +g_irqvector = utils.parse_and_eval("g_irqvector") +NR_IRQS = utils.nitems(g_irqvector) +CONFIG_SCHED_IRQMONITOR = utils.has_field(g_irqvector, "count") + + +class IRQInfo(utils.Value, p.IRQInfo): + def __init__(self, irq: gdb.Value): + super().__init__(irq) + + @property + def count(self) -> int: + return self["count"] if CONFIG_SCHED_IRQMONITOR else -1 + + @property + def time(self) -> int: + return self["time"] if CONFIG_SCHED_IRQMONITOR else -1 + + @property + def start(self) -> int: + return self["start"] if CONFIG_SCHED_IRQMONITOR else -1 + + +def get_irqs() -> List[IRQInfo]: + return (IRQInfo(irq) for irq in utils.ArrayIterator(g_irqvector)) + + +class IRQInfoDump(gdb.Command): + """Dump irqinfo""" + + formatter = "{:<4} {:<10} {:<6} {:<6} {:<48} {} " + header = ("IRQ", "COUNT", "TIME", "RATE", "HANDLER", "ARGUMENT") + + def __init__(self): + super().__init__("irqinfo", gdb.COMMAND_USER) + + def invoke(self, arg: str, from_tty: bool) -> None: + irq_unexpected_isr = utils.gdb_eval_or_none("irq_unexpected_isr") + + print(self.formatter.format(*self.header)) + for i, irq in enumerate(get_irqs()): + if not irq.handler or (int(irq.handler) & ~0x01) == irq_unexpected_isr: + continue + + handler = irq.handler.format_string(styling=True, address=False).strip("<>") + irq_arg = irq.arg.format_string(styling=True) + + print( + self.formatter.format(i, irq.count, irq.time, "N/A", handler, irq_arg) + ) diff --git a/tools/pynuttx/nxgdb/protocols/irq.py b/tools/pynuttx/nxgdb/protocols/irq.py new file mode 100644 index 00000000000..087a419cf72 --- /dev/null +++ b/tools/pynuttx/nxgdb/protocols/irq.py @@ -0,0 +1,35 @@ +############################################################################ +# tools/pynuttx/nxgdb/protocols/irq.py +# +# SPDX-License-Identifier: Apache-2.0 +# +# Licensed to the Apache Software Foundation (ASF) under one or more +# contributor license agreements. See the NOTICE file distributed with +# this work for additional information regarding copyright ownership. The +# ASF licenses this file to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance with the +# License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# +############################################################################ + +from __future__ import annotations + +from .value import Value + + +class IRQInfo(Value): + """struct irq_info_s""" + + handler: Value + arg: Value + start: Value + time: Value + count: Value -- Gitee From acc6de2981e3fae143061877285d777963c648af Mon Sep 17 00:00:00 2001 From: xuxingliang Date: Wed, 27 Nov 2024 15:24:48 +0800 Subject: [PATCH 031/235] nxgdb/memdump: add free command VELAPLATFO-48441 (gdb) free name total used free maxused maxfree nused nfree GImageCache 10485756 10411964 73792 10602184 62328 217 7 uncache 10485756 127812 10357944 270512 10350560 4 2 Umem 26879516 17458732 9420784 20957888 9260768 1211 234 (gdb) Change-Id: Ic78cc1c2a59facdc428e0ed909d57c84b3f18f3c Signed-off-by: xuxingliang --- tools/pynuttx/nxgdb/memdump.py | 64 ++++++++++++++++++++++++++++++++++ 1 file changed, 64 insertions(+) diff --git a/tools/pynuttx/nxgdb/memdump.py b/tools/pynuttx/nxgdb/memdump.py index c16ef04e98a..ec53ca38048 100644 --- a/tools/pynuttx/nxgdb/memdump.py +++ b/tools/pynuttx/nxgdb/memdump.py @@ -96,6 +96,7 @@ def group_nodes( ) -> Dict[MMNodeDump, List[MMNodeDump]]: grouped = grouped or defaultdict(list) for node in nodes: + # default to group by same PID, same size and same backtrace grouped[node].append(node) return grouped @@ -525,3 +526,66 @@ class MMMap(gdb.Command): output = args.output or f"{name}.png" self.save_memory_map(heap.nodes_used(), output) gdb.write(f"Memory map saved to {output}\n") + + +class MMFree(gdb.Command): + """Show heap statistics, same as device command free""" + + def __init__(self): + super().__init__("mm free", gdb.COMMAND_USER) + utils.alias("free", "mm free") + + def invoke(self, args, from_tty): + heaps = mm.get_heaps() + + formatter = "{:<20} {:<10} {:<10} {:<10} {:<10} {:<10} {:<10} {:<10}" + header = ( + "name", + "total", + "used", + "free", + "maxused", + "maxfree", + "nused", + "nfree", + ) + + print(formatter.format(*header)) + mm_heap_s = utils.lookup_type("struct mm_heap_s") + for heap in heaps: + heap_free = heap_used = 0 + total_size = max_free = nused = nfree = 0 + for node in heap.nodes: + nodesize = node.nodesize + total_size += nodesize + + if node.is_free: + nfree += 1 + heap_free += nodesize + max_free = max(max_free, nodesize) + else: + heap_used += nodesize + nused += 1 + + mempool_free = sum( + blk.nodesize + for pool in mm.get_pools([heap]) + for blk in pool.blks + if blk.is_free + ) + + total = heap.heapsize + mm_heap_s.sizeof + heap_used += mm_heap_s.sizeof # struct overhead + + print( + formatter.format( + heap.name, + total, + heap_used - mempool_free, + heap_free + mempool_free, + int(heap.mm_maxused), + max_free, + nused, + nfree, + ) + ) -- Gitee From 87c82ce4c1349f19a1118a2e0c9c30169d8f93a7 Mon Sep 17 00:00:00 2001 From: xuxingliang Date: Mon, 2 Dec 2024 16:37:42 +0800 Subject: [PATCH 032/235] pynuttx: fix memleak that should only check used node VELAPLATFO-45086 Change-Id: Ibbd2f781975ce5a2ce7be4b8d6fa47a9e5fe2fe6 Signed-off-by: xuxingliang --- tools/pynuttx/nxgdb/memleak.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/tools/pynuttx/nxgdb/memleak.py b/tools/pynuttx/nxgdb/memleak.py index 45baafb7edb..83445937744 100644 --- a/tools/pynuttx/nxgdb/memleak.py +++ b/tools/pynuttx/nxgdb/memleak.py @@ -112,7 +112,9 @@ class MMLeak(gdb.Command): sorted_addr = set() t = time.time() print("Gather memory nodes...", flush=True, end="") - for node in memdump.dump_nodes(heaps, {"no_pid": mm.PID_MM_MEMPOOL}): + for node in memdump.dump_nodes( + heaps, {"no_pid": mm.PID_MM_MEMPOOL, "used": True} + ): nodes_dict[node.address] = node sorted_addr.add(node.address) -- Gitee From 74c6f03c23b60d6f7e155114a8639134948c0b92 Mon Sep 17 00:00:00 2001 From: xuxingliang Date: Mon, 2 Dec 2024 17:11:55 +0800 Subject: [PATCH 033/235] pynuttx: optimize memory leak check by skipping previously checked pointers VELAPLATFO-45086 Reduce leak analysis time from 12s to 7.8s, achieving a 35% performance improvement that tested on an internal project. 1. Use memoryview to avoid creating int objects, reducing overhead 2. Store checked pointers in a dictionary for efficient lookups, improving performance. 3. While dictionary operations have some cost, the overall speedup is significant. Change-Id: I014a94b8595d6cf7eb3fa1f31970e5da565996f3 Signed-off-by: xuxingliang --- tools/pynuttx/nxgdb/memleak.py | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/tools/pynuttx/nxgdb/memleak.py b/tools/pynuttx/nxgdb/memleak.py index 83445937744..5ebf0376ba4 100644 --- a/tools/pynuttx/nxgdb/memleak.py +++ b/tools/pynuttx/nxgdb/memleak.py @@ -129,19 +129,34 @@ class MMLeak(gdb.Command): longsize = utils.get_long_type().sizeof + checked_ptr = {} + def pointers(node: memdump.MMNodeDump) -> Generator[int, None, None]: # Return all possible pointers stored in this node size = node.nodesize - node.overhead memory = node.read_memory() + prev_mem = None while size > 0: size -= longsize - ptr = int.from_bytes(memory[size : size + longsize], "little") + mem = memory[size : size + longsize] + if mem == prev_mem: + continue + + prev_mem = mem + ptr = int.from_bytes(mem, "little") + if ptr in checked_ptr: + continue + + checked_ptr[ptr] = True + if any(region["start"] <= ptr < region["end"] for region in regions): yield ptr print("Leak analyzing...", flush=True, end="") t = time.time() for good in good_nodes: + if not sorted_addr: # All nodes are checked + break for ptr in pointers(good): if not (idx := bisect.bisect_right(sorted_addr, ptr)): continue -- Gitee From 52b0cb8f90b265694c7ebb954e24d3e1f9475300 Mon Sep 17 00:00:00 2001 From: xuxingliang Date: Mon, 2 Dec 2024 12:08:21 +0800 Subject: [PATCH 034/235] nxgdb: fix typo reviewd from upstream VELAPLATFO-45086 Change-Id: I94230ca9442c9bbdb301985e80ec7f7f10211787 Signed-off-by: xuxingliang --- tools/pynuttx/gdbinit.py | 2 ++ tools/pynuttx/nxgdb/__init__.py | 2 ++ tools/pynuttx/nxgdb/debug.py | 2 ++ tools/pynuttx/nxgdb/diagnose.py | 2 ++ tools/pynuttx/nxgdb/dmesg.py | 2 ++ tools/pynuttx/nxgdb/fs.py | 2 ++ tools/pynuttx/nxgdb/gcore.py | 2 ++ tools/pynuttx/nxgdb/lists.py | 2 ++ tools/pynuttx/nxgdb/macros.py | 12 +++++++----- tools/pynuttx/nxgdb/memcheck.py | 2 ++ tools/pynuttx/nxgdb/memdump.py | 10 ++++++---- tools/pynuttx/nxgdb/memleak.py | 2 ++ tools/pynuttx/nxgdb/mm.py | 2 ++ tools/pynuttx/nxgdb/net.py | 2 ++ tools/pynuttx/nxgdb/prefix.py | 2 ++ tools/pynuttx/nxgdb/profile.py | 2 ++ tools/pynuttx/nxgdb/protocols/fs.py | 2 ++ tools/pynuttx/nxgdb/protocols/mm.py | 4 +++- tools/pynuttx/nxgdb/protocols/thread.py | 2 ++ tools/pynuttx/nxgdb/protocols/value.py | 2 ++ tools/pynuttx/nxgdb/rpmsg.py | 2 ++ tools/pynuttx/nxgdb/stack.py | 2 ++ tools/pynuttx/nxgdb/thread.py | 2 ++ tools/pynuttx/nxgdb/utils.py | 6 ++++-- 24 files changed, 60 insertions(+), 12 deletions(-) diff --git a/tools/pynuttx/gdbinit.py b/tools/pynuttx/gdbinit.py index 556b42808ea..a965fa34850 100644 --- a/tools/pynuttx/gdbinit.py +++ b/tools/pynuttx/gdbinit.py @@ -1,6 +1,8 @@ ############################################################################ # tools/pynuttx/gdbinit.py # +# SPDX-License-Identifier: Apache-2.0 +# # Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with # this work for additional information regarding copyright ownership. The diff --git a/tools/pynuttx/nxgdb/__init__.py b/tools/pynuttx/nxgdb/__init__.py index 6f91a91b6ab..254cf268e4f 100644 --- a/tools/pynuttx/nxgdb/__init__.py +++ b/tools/pynuttx/nxgdb/__init__.py @@ -1,6 +1,8 @@ ############################################################################ # tools/pynuttx/nxgdb/__init__.py # +# SPDX-License-Identifier: Apache-2.0 +# # Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with # this work for additional information regarding copyright ownership. The diff --git a/tools/pynuttx/nxgdb/debug.py b/tools/pynuttx/nxgdb/debug.py index 13b811eaa8a..35858b61d2c 100644 --- a/tools/pynuttx/nxgdb/debug.py +++ b/tools/pynuttx/nxgdb/debug.py @@ -1,6 +1,8 @@ ############################################################################ # tools/pynuttx/nxgdb/debug.py # +# SPDX-License-Identifier: Apache-2.0 +# # Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with # this work for additional information regarding copyright ownership. The diff --git a/tools/pynuttx/nxgdb/diagnose.py b/tools/pynuttx/nxgdb/diagnose.py index 7518fc70695..0a0f694fb44 100644 --- a/tools/pynuttx/nxgdb/diagnose.py +++ b/tools/pynuttx/nxgdb/diagnose.py @@ -1,6 +1,8 @@ ############################################################################ # tools/pynuttx/nxgdb/diagnose.py # +# SPDX-License-Identifier: Apache-2.0 +# # Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with # this work for additional information regarding copyright ownership. The diff --git a/tools/pynuttx/nxgdb/dmesg.py b/tools/pynuttx/nxgdb/dmesg.py index 6db1e4cf199..8f4a487c5f9 100644 --- a/tools/pynuttx/nxgdb/dmesg.py +++ b/tools/pynuttx/nxgdb/dmesg.py @@ -1,6 +1,8 @@ ############################################################################ # tools/pynuttx/nxgdb/dmesg.py # +# SPDX-License-Identifier: Apache-2.0 +# # Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with # this work for additional information regarding copyright ownership. The diff --git a/tools/pynuttx/nxgdb/fs.py b/tools/pynuttx/nxgdb/fs.py index a351e7111cb..4db3f25e132 100644 --- a/tools/pynuttx/nxgdb/fs.py +++ b/tools/pynuttx/nxgdb/fs.py @@ -1,6 +1,8 @@ ############################################################################ # tools/pynuttx/nxgdb/fs.py # +# SPDX-License-Identifier: Apache-2.0 +# # Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with # this work for additional information regarding copyright ownership. The diff --git a/tools/pynuttx/nxgdb/gcore.py b/tools/pynuttx/nxgdb/gcore.py index 93e2e330055..8a2deabfaee 100644 --- a/tools/pynuttx/nxgdb/gcore.py +++ b/tools/pynuttx/nxgdb/gcore.py @@ -1,6 +1,8 @@ ############################################################################ # tools/pynuttx/nxgdb/gcore.py # +# SPDX-License-Identifier: Apache-2.0 +# # Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with # this work for additional information regarding copyright ownership. The diff --git a/tools/pynuttx/nxgdb/lists.py b/tools/pynuttx/nxgdb/lists.py index b08e94fb19d..0c6222f1fb3 100644 --- a/tools/pynuttx/nxgdb/lists.py +++ b/tools/pynuttx/nxgdb/lists.py @@ -1,6 +1,8 @@ ############################################################################ # tools/pynuttx/nxgdb/lists.py # +# SPDX-License-Identifier: Apache-2.0 +# # Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with # this work for additional information regarding copyright ownership. The diff --git a/tools/pynuttx/nxgdb/macros.py b/tools/pynuttx/nxgdb/macros.py index 12564dd9313..b6edeffddca 100644 --- a/tools/pynuttx/nxgdb/macros.py +++ b/tools/pynuttx/nxgdb/macros.py @@ -1,6 +1,8 @@ ############################################################################ # tools/pynuttx/nxgdb/macros.py # +# SPDX-License-Identifier: Apache-2.0 +# # Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with # this work for additional information regarding copyright ownership. The @@ -26,14 +28,14 @@ # then parse and evaluate it by ourselves. # # There might be two ways to achieve this, one is to leverage the C preprocessor -# to directly preprocess all the macros instereted into python constants +# to directly preprocess all the macros interpreted into python constants # gcc -E -x c -P -I/path/to/nuttx/include # # While the other way is to leverage the dwarf info stored in the ELF file, # with -g3 switch, we have a `.debug_macro` section containing all the information # about the macros. # -# Currently, we using the second method. +# Currently, we are using the second method. import hashlib import json @@ -192,9 +194,9 @@ def do_expand(expr, macro_map): # NOTE: Implement a fully functional parser which can -# preprocessing all the C marcos according to ISO 9899 standard +# preprocess all the C marcos according to ISO 9899 standard # may be an overkill, what we really care about are those -# macros that can be evaluted to an constant value. +# macros that can be evaluated to an constant value. # # #define A (B + C + D) # #define B 1 @@ -210,7 +212,7 @@ def do_expand(expr, macro_map): # use case for it in our GDB plugin. # # However, you can switch to the correct stack frame that has this macro defined -# and let GDB expand and evaluate it for you if you really want to evalue some very +# and let GDB expand and evaluate it for you if you really want to evaluate some very # complex macros. diff --git a/tools/pynuttx/nxgdb/memcheck.py b/tools/pynuttx/nxgdb/memcheck.py index f503729f763..4cb1c51d6a4 100644 --- a/tools/pynuttx/nxgdb/memcheck.py +++ b/tools/pynuttx/nxgdb/memcheck.py @@ -1,6 +1,8 @@ ############################################################################ # tools/pynuttx/nxgdb/memcheck.py # +# SPDX-License-Identifier: Apache-2.0 +# # Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with # this work for additional information regarding copyright ownership. The diff --git a/tools/pynuttx/nxgdb/memdump.py b/tools/pynuttx/nxgdb/memdump.py index ec53ca38048..2b42ae199c5 100644 --- a/tools/pynuttx/nxgdb/memdump.py +++ b/tools/pynuttx/nxgdb/memdump.py @@ -1,6 +1,8 @@ ############################################################################ # tools/pynuttx/nxgdb/memdump.py # +# SPDX-License-Identifier: Apache-2.0 +# # Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with # this work for additional information regarding copyright ownership. The @@ -354,10 +356,10 @@ class MMDump(gdb.Command): printnode(node, 1) print(f"{addr: #x} found belongs to {source} - {node}") - if node.prevnode: - print(f"prevnode: {node.prevnode}") - if node.nextnode: - print(f"nextnode: {node.nextnode}") + if node.prevnode: + print(f"prevnode: {node.prevnode}") + if node.nextnode: + print(f"nextnode: {node.nextnode}") return filters = { diff --git a/tools/pynuttx/nxgdb/memleak.py b/tools/pynuttx/nxgdb/memleak.py index 5ebf0376ba4..314db6a7c29 100644 --- a/tools/pynuttx/nxgdb/memleak.py +++ b/tools/pynuttx/nxgdb/memleak.py @@ -1,6 +1,8 @@ ############################################################################ # tools/pynuttx/nxgdb/memleak.py # +# SPDX-License-Identifier: Apache-2.0 +# # Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with # this work for additional information regarding copyright ownership. The diff --git a/tools/pynuttx/nxgdb/mm.py b/tools/pynuttx/nxgdb/mm.py index ac8cb31bcae..7104a1ce73a 100644 --- a/tools/pynuttx/nxgdb/mm.py +++ b/tools/pynuttx/nxgdb/mm.py @@ -1,6 +1,8 @@ ############################################################################ # tools/pynuttx/nxgdb/mm.py # +# SPDX-License-Identifier: Apache-2.0 +# # Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with # this work for additional information regarding copyright ownership. The diff --git a/tools/pynuttx/nxgdb/net.py b/tools/pynuttx/nxgdb/net.py index bc5bf75dc2c..ffb23a113d4 100644 --- a/tools/pynuttx/nxgdb/net.py +++ b/tools/pynuttx/nxgdb/net.py @@ -1,6 +1,8 @@ ############################################################################ # tools/pynuttx/nxgdb/net.py # +# SPDX-License-Identifier: Apache-2.0 +# # Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with # this work for additional information regarding copyright ownership. The diff --git a/tools/pynuttx/nxgdb/prefix.py b/tools/pynuttx/nxgdb/prefix.py index db1d3923172..b232a854dd0 100644 --- a/tools/pynuttx/nxgdb/prefix.py +++ b/tools/pynuttx/nxgdb/prefix.py @@ -1,6 +1,8 @@ ############################################################################ # tools/pynuttx/nxgdb/prefix.py # +# SPDX-License-Identifier: Apache-2.0 +# # Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with # this work for additional information regarding copyright ownership. The diff --git a/tools/pynuttx/nxgdb/profile.py b/tools/pynuttx/nxgdb/profile.py index c691fd6b18a..1d16abef454 100644 --- a/tools/pynuttx/nxgdb/profile.py +++ b/tools/pynuttx/nxgdb/profile.py @@ -1,6 +1,8 @@ ############################################################################ # tools/pynuttx/nxgdb/profile.py # +# SPDX-License-Identifier: Apache-2.0 +# # Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with # this work for additional information regarding copyright ownership. The diff --git a/tools/pynuttx/nxgdb/protocols/fs.py b/tools/pynuttx/nxgdb/protocols/fs.py index ae29afa43ef..37bbaa00c1d 100644 --- a/tools/pynuttx/nxgdb/protocols/fs.py +++ b/tools/pynuttx/nxgdb/protocols/fs.py @@ -1,6 +1,8 @@ ############################################################################ # tools/pynuttx/nxgdb/protocols/fs.py # +# SPDX-License-Identifier: Apache-2.0 +# # Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with # this work for additional information regarding copyright ownership. The diff --git a/tools/pynuttx/nxgdb/protocols/mm.py b/tools/pynuttx/nxgdb/protocols/mm.py index 6f3eec59cd2..3935b1b09f4 100644 --- a/tools/pynuttx/nxgdb/protocols/mm.py +++ b/tools/pynuttx/nxgdb/protocols/mm.py @@ -1,5 +1,7 @@ ############################################################################ -# tools/pynuttx/nxgdb/protocols/fs.py +# tools/gdb/nuttxgdb/protocols/mm.py +# +# SPDX-License-Identifier: Apache-2.0 # # Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with diff --git a/tools/pynuttx/nxgdb/protocols/thread.py b/tools/pynuttx/nxgdb/protocols/thread.py index 249dd93d010..71e970bea8f 100644 --- a/tools/pynuttx/nxgdb/protocols/thread.py +++ b/tools/pynuttx/nxgdb/protocols/thread.py @@ -1,6 +1,8 @@ ############################################################################ # tools/pynuttx/nxgdb/protocols/thread.py # +# SPDX-License-Identifier: Apache-2.0 +# # Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with # this work for additional information regarding copyright ownership. The diff --git a/tools/pynuttx/nxgdb/protocols/value.py b/tools/pynuttx/nxgdb/protocols/value.py index 5e733bd28b7..2964b94be36 100644 --- a/tools/pynuttx/nxgdb/protocols/value.py +++ b/tools/pynuttx/nxgdb/protocols/value.py @@ -1,6 +1,8 @@ ############################################################################ # tools/pynuttx/nxgdb/protocols/value.py # +# SPDX-License-Identifier: Apache-2.0 +# # Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with # this work for additional information regarding copyright ownership. The diff --git a/tools/pynuttx/nxgdb/rpmsg.py b/tools/pynuttx/nxgdb/rpmsg.py index c19adc4f180..a00e2249351 100644 --- a/tools/pynuttx/nxgdb/rpmsg.py +++ b/tools/pynuttx/nxgdb/rpmsg.py @@ -1,6 +1,8 @@ ############################################################################ # tools/pynuttx/rpmsg.py # +# SPDX-License-Identifier: Apache-2.0 +# # Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with # this work for additional information regarding copyright ownership. The diff --git a/tools/pynuttx/nxgdb/stack.py b/tools/pynuttx/nxgdb/stack.py index 6dd7b782b85..132cb9a84d3 100644 --- a/tools/pynuttx/nxgdb/stack.py +++ b/tools/pynuttx/nxgdb/stack.py @@ -1,6 +1,8 @@ ############################################################################ # tools/pynuttx/nxgdb/stack.py # +# SPDX-License-Identifier: Apache-2.0 +# # Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with # this work for additional information regarding copyright ownership. The diff --git a/tools/pynuttx/nxgdb/thread.py b/tools/pynuttx/nxgdb/thread.py index 4fc8ab9d894..a996b1021aa 100644 --- a/tools/pynuttx/nxgdb/thread.py +++ b/tools/pynuttx/nxgdb/thread.py @@ -1,6 +1,8 @@ ############################################################################ # tools/pynuttx/nxgdb/thread.py # +# SPDX-License-Identifier: Apache-2.0 +# # Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with # this work for additional information regarding copyright ownership. The diff --git a/tools/pynuttx/nxgdb/utils.py b/tools/pynuttx/nxgdb/utils.py index 6eb1dfea4ad..8e9be82c5bf 100644 --- a/tools/pynuttx/nxgdb/utils.py +++ b/tools/pynuttx/nxgdb/utils.py @@ -1,6 +1,8 @@ ############################################################################ # tools/pynuttx/nxgdb/utils.py # +# SPDX-License-Identifier: Apache-2.0 +# # Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with # this work for additional information regarding copyright ownership. The @@ -654,7 +656,7 @@ target_arch = None def is_target_arch(arch, exact=False): """ - For non exactly match, this function will + For non exact match, this function will return True if the target architecture contains keywords of an ARCH family. For example, x86 is contained in i386:x86_64. @@ -711,7 +713,7 @@ def in_interrupt_context(cpuid=0): def get_register_byname(regname, tcb=None): frame = gdb.selected_frame() - # If no tcb is given then we can directly used the register from + # If no tcb is given then we can directly use the register from # the cached frame by GDB if not tcb: return int(frame.read_register(regname)) -- Gitee From 025cb3d7d208bc3a827ee7b0c0b3dbe4c62923db Mon Sep 17 00:00:00 2001 From: xuxingliang Date: Thu, 28 Nov 2024 13:58:43 +0800 Subject: [PATCH 035/235] nxgdb/mm: show pool expand queue size VELAPLATFO-45086 Change-Id: I88bc95700e5483e246edd9ac4c55879954fee566 Signed-off-by: xuxingliang --- tools/pynuttx/nxgdb/mm.py | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/tools/pynuttx/nxgdb/mm.py b/tools/pynuttx/nxgdb/mm.py index 7104a1ce73a..d1e3ca42420 100644 --- a/tools/pynuttx/nxgdb/mm.py +++ b/tools/pynuttx/nxgdb/mm.py @@ -183,6 +183,10 @@ class MemPool(Value, p.MemPool): ninit = 0 yield (int(entry) - blks * blksize, int(entry)) + @property + def nqueue(self) -> int: + return lists.sq_count(self.equeue) + @property def size(self) -> int: """Real block size including backtrace overhead""" @@ -643,7 +647,7 @@ class MMPoolInfo(gdb.Command): name_max = max(len(pool.name) for pool in pools) + 11 # 11: "@0x12345678" formatter = ( - "{:>%d} {:>11} {:>9} {:>9} {:>9} {:>9} {:>9} {:>9} {:>9}\n" % name_max + "{:>%d} {:>11} {:>9} {:>9} {:>9} {:>9} {:>9} {:>9} {:>9} {:>9}\n" % name_max ) head = ( "", @@ -655,6 +659,7 @@ class MMPoolInfo(gdb.Command): "nfree", "nifree", "nwaiter", + "nqueue", ) gdb.write(formatter.format(*head)) @@ -670,5 +675,6 @@ class MMPoolInfo(gdb.Command): pool.nfree, pool.nifree, pool.nwaiter, + pool.nqueue, ) ) -- Gitee From 48a47d68a71d7d5020a4778b6e8622837addb816 Mon Sep 17 00:00:00 2001 From: xuxingliang Date: Fri, 29 Nov 2024 09:27:47 +0800 Subject: [PATCH 036/235] nxgdb/thread: fix ps command VELAPLATFO-45086 Fix ps command reports wrong running stack corruption. To get running tcb registers, need to read from frame register not the tcb context. Change-Id: I38bcbb8d40029852f22f1f91e7861a2275c39487 Signed-off-by: xuxingliang --- tools/pynuttx/nxgdb/thread.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/pynuttx/nxgdb/thread.py b/tools/pynuttx/nxgdb/thread.py index a996b1021aa..a1e98f40d89 100644 --- a/tools/pynuttx/nxgdb/thread.py +++ b/tools/pynuttx/nxgdb/thread.py @@ -514,7 +514,7 @@ class Ps(gdb.Command): int(tcb["stack_base_ptr"]), int(tcb["stack_alloc_ptr"]), int(tcb["adj_stack_size"]), - utils.get_sp(tcb), + utils.get_sp(tcb if tcb["task_state"] != TSTATE_TASK_RUNNING else None), 4, ) -- Gitee From 993fdf494a428db087307c6588fea245fbc00461 Mon Sep 17 00:00:00 2001 From: yinshengkai Date: Mon, 25 Nov 2024 17:06:55 +0800 Subject: [PATCH 037/235] tools: move macros.py to pynuttx/elf VELAPLATFO-47018 Change-Id: Ibc5ab9a10ab7633cea133c3485cecd7f99be8d7e Signed-off-by: yinshengkai --- tools/pynuttx/{nxgdb => nxelf}/macros.py | 2 +- tools/pynuttx/nxgdb/utils.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) rename tools/pynuttx/{nxgdb => nxelf}/macros.py (99%) diff --git a/tools/pynuttx/nxgdb/macros.py b/tools/pynuttx/nxelf/macros.py similarity index 99% rename from tools/pynuttx/nxgdb/macros.py rename to tools/pynuttx/nxelf/macros.py index b6edeffddca..ce207a60e08 100644 --- a/tools/pynuttx/nxgdb/macros.py +++ b/tools/pynuttx/nxelf/macros.py @@ -1,5 +1,5 @@ ############################################################################ -# tools/pynuttx/nxgdb/macros.py +# tools/pynuttx/nxelf/macros.py # # SPDX-License-Identifier: Apache-2.0 # diff --git a/tools/pynuttx/nxgdb/utils.py b/tools/pynuttx/nxgdb/utils.py index 8e9be82c5bf..8eccfc588f5 100644 --- a/tools/pynuttx/nxgdb/utils.py +++ b/tools/pynuttx/nxgdb/utils.py @@ -33,8 +33,8 @@ from enum import Enum from typing import List, Optional, Tuple, Union import gdb +from nxelf.macros import fetch_macro_info, try_expand -from .macros import fetch_macro_info, try_expand from .protocols.thread import Tcb g_symbol_cache = {} -- Gitee From 03774959145d9d55ea433df3e9750f30270db433 Mon Sep 17 00:00:00 2001 From: xuxingliang Date: Tue, 3 Dec 2024 11:50:08 +0800 Subject: [PATCH 038/235] pynuttx: use namespace packages to include nxgdb and nxelf VELAPLATFO-48924 Change-Id: I2529afdc75f09399d3c499a5be794b0832fc6743 Signed-off-by: xuxingliang --- tools/pynuttx/.gitignore | 2 +- tools/pynuttx/nxelf/__init__.py | 19 +++++++++++++++++++ tools/pynuttx/pyproject.toml | 22 ---------------------- tools/pynuttx/setup.py | 14 ++++++++++++++ 4 files changed, 34 insertions(+), 23 deletions(-) create mode 100644 tools/pynuttx/nxelf/__init__.py delete mode 100644 tools/pynuttx/pyproject.toml create mode 100644 tools/pynuttx/setup.py diff --git a/tools/pynuttx/.gitignore b/tools/pynuttx/.gitignore index 1abceb8f415..eba7c7157a8 100644 --- a/tools/pynuttx/.gitignore +++ b/tools/pynuttx/.gitignore @@ -1,2 +1,2 @@ dist/ -nxgdb.egg-info/ +pynuttx.egg-info/ diff --git a/tools/pynuttx/nxelf/__init__.py b/tools/pynuttx/nxelf/__init__.py new file mode 100644 index 00000000000..1e74d508193 --- /dev/null +++ b/tools/pynuttx/nxelf/__init__.py @@ -0,0 +1,19 @@ +############################################################################ +# tools/pynuttx/nxelf/__init__.py +# +# Licensed to the Apache Software Foundation (ASF) under one or more +# contributor license agreements. See the NOTICE file distributed with +# this work for additional information regarding copyright ownership. The +# ASF licenses this file to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance with the +# License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# +############################################################################ diff --git a/tools/pynuttx/pyproject.toml b/tools/pynuttx/pyproject.toml deleted file mode 100644 index d8dc6577236..00000000000 --- a/tools/pynuttx/pyproject.toml +++ /dev/null @@ -1,22 +0,0 @@ -[build-system] -requires = ["setuptools>=61", "wheel"] -build-backend = "setuptools.build_meta" - -[project] -version = "0.0.1" -name = 'nxgdb' -description = 'NuttX RTOS GDB extensions' -readme = "README.md" -license = { file = 'LICENSE' } -classifiers = [ - "Intended Audience :: Developers", - "License :: OSI Approved :: Apache Software License", - "Programming Language :: Python", - "Programming Language :: Python :: 3", -] - -dependencies = ["matplotlib", "numpy", "pyelftools"] -requires-python = ">=3.8" - -[tool.setuptools.package-dir] -nxgdb = "nxgdb" diff --git a/tools/pynuttx/setup.py b/tools/pynuttx/setup.py new file mode 100644 index 00000000000..844e5dc5de9 --- /dev/null +++ b/tools/pynuttx/setup.py @@ -0,0 +1,14 @@ +from setuptools import find_packages, setup + +setup( + name="pynuttx", + version="0.0.1", + packages=find_packages(include=["nxgdb", "nxelf"]), + install_requires=[], + description="NuttX python development tools", + classifiers=[ + "Programming Language :: Python :: 3", + "License :: OSI Approved :: Apache Software License", + ], + requires=["matplotlib", "numpy", "pyelftools", "debugpy"], +) -- Gitee From 228a19c792c18f7547110acbc43df12048ed73e4 Mon Sep 17 00:00:00 2001 From: anjiahao Date: Thu, 5 Dec 2024 09:10:07 +0800 Subject: [PATCH 039/235] thread.py:tcbinfo_current_regs rename to tcbinfo_running_regs VELAPLATFO-45086 Change-Id: I51188b65dfac8962154c7037987d05dede818d8b Signed-off-by: anjiahao --- tools/pynuttx/nxgdb/thread.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tools/pynuttx/nxgdb/thread.py b/tools/pynuttx/nxgdb/thread.py index a1e98f40d89..359d75cdefd 100644 --- a/tools/pynuttx/nxgdb/thread.py +++ b/tools/pynuttx/nxgdb/thread.py @@ -166,7 +166,7 @@ class SetRegs(gdb.Command): setregs tcb->xcp.regs setregs g_pidhash[0]->xcp.regs - Default regs is tcbinfo_current_regs(),if regs is NULL, it will not set registers. + Default regs is tcbinfo_running_regs(),if regs is NULL, it will not set registers. """ def __init__(self): @@ -181,7 +181,7 @@ class SetRegs(gdb.Command): "regs", nargs="?", default="", - help="The registers to set, use tcbinfo_current_regs() if not specified", + help="The registers to set, use tcbinfo_running_regs() if not specified", ) try: @@ -194,7 +194,7 @@ class SetRegs(gdb.Command): utils.lookup_type("char").pointer() ) else: - current_regs = gdb.parse_and_eval("tcbinfo_current_regs()") + current_regs = gdb.parse_and_eval("tcbinfo_running_regs()") regs = current_regs.cast(utils.lookup_type("char").pointer()) if regs == 0: -- Gitee From c46df62b7228a3e8cb366454442e49b3410eca45 Mon Sep 17 00:00:00 2001 From: yinshengkai Date: Wed, 20 Nov 2024 15:21:19 +0800 Subject: [PATCH 040/235] tools: add elf parser library VELAPLATFO-48504 ELF file parser class for extracting the following information from ELF files: - Symbol addresses - Structure definitions - Enumeration type definitions - Enumeration values It can convert binary data into Python classes that match the structure in elf elf_parser = ELFParser("nuttx") struct = elf_parser.get_type("file_operations") # Returns construct.Struct object print(struct._subcons) # result: Container: open = > close = > read = > write = > seek = > ioctl = > mmap = > truncate = > poll = > unlink = > Change-Id: I7b6717dea58b15d1dd1bbf4b333e7cdb3801abff Signed-off-by: yinshengkai --- tools/pynuttx/nxelf/elf.py | 388 +++++++++++++++++++++++++++++++++++++ 1 file changed, 388 insertions(+) create mode 100644 tools/pynuttx/nxelf/elf.py diff --git a/tools/pynuttx/nxelf/elf.py b/tools/pynuttx/nxelf/elf.py new file mode 100644 index 00000000000..5ae432be093 --- /dev/null +++ b/tools/pynuttx/nxelf/elf.py @@ -0,0 +1,388 @@ +#! /usr/bin/env python3 +############################################################################ +# tools/pynuttx/nxelf/elf.py +# +# Licensed to the Apache Software Foundation (ASF) under one or more +# contributor license agreements. See the NOTICE file distributed with +# this work for additional information regarding copyright ownership. The +# ASF licenses this file to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance with the +# License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# +############################################################################ + +import logging +import time +from enum import IntEnum + +from .macros import Macro + +try: + import construct + import cxxfilt + from elftools.elf.elffile import ELFFile + from elftools.elf.sections import SymbolTableSection +except ModuleNotFoundError: + print("Please execute the following command to install dependencies:") + print("pip install construct pyelftools cxxfilt") + exit(1) + +logging.basicConfig(level=logging.WARNING) +logger = logging.getLogger(__name__) + + +class TypeConflictError(Exception): + """ + Symbols have different definitions + """ + + pass + + +class Types: + def __init__(self, tag): + self.types = {} + self.tag = tag + self.result = dict() + + def set_type(self, die): + if "DW_AT_name" not in die.attributes: + return + + name = die.attributes["DW_AT_name"].value.decode("utf-8") + if name not in self.types: + self.types[name] = set() + + self.types[name].add(die) + + def get_types(self, type_name): + if type_name in self.types: + sets = self.types[type_name] + return sets + else: + return None + + def set_result(self, type_name, result): + if len(result) != 1: + raise TypeConflictError( + f"Multiple different definitions or values ​​exist for a symbol: {type_name} {result}" + ) + + result = result.pop() + if type_name in self.types: + self.result[type_name] = result + return result + + def get_result(self, type_name): + if type_name in self.result: + return self.result[type_name] + return None + + +class ELFParser: + """ + ELF file parser class for extracting the following information from ELF files: + - Symbol addresses + - Structure definitions + - Enumeration type definitions + - Enumeration values + + Main functionality: + 1. Get structure definitions + elf_parser = ELFParser("nuttx") + struct = elf_parser.get_type("file_operations") # Returns construct.Struct object + print(struct._subcons) + + # result: + Container: + open = > + close = > + read = > + write = > + seek = > + ioctl = > + mmap = > + truncate = > + poll = > + unlink = > + + 2. Get symbol addresses + addr = elf_parser.symbol_addr("_SeggerRTT") # Returns symbol address + + 3. Get enumeration type definitions + enum = elf_parser.get_type("tstate_e") # Returns construct.IntEnum object + + 4. Get enumeration values + value = elf_parser.enum_value("TSTATE_TASK_RUNNING") # Returns integer value + + """ + + def __init__(self, elf_path): + self.elf = ELFFile(open(elf_path, "rb")) + self.types = dict() + self.info = dict() + self.symbol = dict() + self.dwarf = self.elf.get_dwarf_info() + + t = time.time() + print("Parsing ELF file...") + self.parse_header() + self.parse_types() + self.macro = Macro(elf_path) + print(f"ELF file parsed in {time.time() - t:.1f} seconds") + + def parse_header(self): + header = self.elf.header + self.info["bitwides"] = ( + 32 if header["e_ident"]["EI_CLASS"] == "ELFCLASS32" else 64 + ) + self.info["byteorder"] = ( + "little" if header["e_ident"]["EI_DATA"] == "ELFDATA2LSB" else "big" + ) + self.info["arch"] = header["e_machine"] + self.info["size_t"] = "uint%d" % self.info["bitwides"] + + def parse_symbol(self): + tables = [ + s + for _, s in enumerate(self.elf.iter_sections()) + if isinstance(s, SymbolTableSection) + and s.name == ".symtab" + and s["sh_entsize"] + ] + + for section in tables: + for nsym, symbol in enumerate(section.iter_symbols()): + try: + name = cxxfilt.demangle(symbol.name) + except Exception: + name = symbol.name + self.symbol[name] = symbol["st_value"] + + def symbol_addr(self, name): + if len(self.symbol.keys()) == 0: + self.parse_symbol() + + if name not in self.symbol: + return None + + return self.symbol[name] + + def parse_types(self): + for CU in self.elf.get_dwarf_info().iter_CUs(): + # Iterate all DIEs in CU and save them by tag + for DIE in CU.iter_DIEs(): + # If the type is already in the dictionary, add the die to the set + if DIE.tag in self.types.keys(): + self.types[DIE.tag].set_type(DIE) + else: + self.types[DIE.tag] = Types(DIE.tag) + self.types[DIE.tag].set_type(DIE) + + def parse_array(self, die): + nums = 0 + for child in die.iter_children(): + nums = child.attributes["DW_AT_upper_bound"].value + + type_die = self.dwarf.get_DIE_from_refaddr( + die.attributes["DW_AT_type"].value + die.cu.cu_offset + ) + + item_type = self.parse_die(type_die) + array = construct.Array(nums, item_type) + return array + + def parse_die(self, die): + if die.tag == "DW_TAG_structure_type": + if "DW_AT_name" not in die.attributes: + return None + ret = self.struct(die.attributes["DW_AT_name"].value.decode("utf-8")) + return ret + elif die.tag == "DW_TAG_enumeration_type": + if "DW_AT_name" not in die.attributes: + return None + return self.enum(die.attributes["DW_AT_name"].value.decode("utf-8")) + elif die.tag == "DW_TAG_base_type": + if "DW_AT_name" not in die.attributes: + return None + return self.base_type(die.attributes["DW_AT_name"].value.decode("utf-8")) + elif die.tag == "DW_TAG_typedef": + if "DW_AT_name" not in die.attributes: + return None + return self.typedef(die.attributes["DW_AT_name"].value.decode("utf-8")) + elif die.tag == "DW_TAG_pointer_type": + if self.info["bitwides"] == 32: + return construct.Int32ul + elif self.info["bitwides"] == 64: + return construct.Int64ul + else: + raise ValueError("Unsupported ELF class") + elif die.tag == "DW_TAG_array_type": + return self.parse_array(die) + else: + raise ValueError(f"Unsupported type: {die.tag}") + + def get_type(self, type_name): + if len(self.types.keys()) == 0: + self.parse_types() + + for key, value in self.types.items(): + if type_name in value.types.keys(): + if key == "DW_TAG_structure_type": + return self.struct(type_name) + elif key == "DW_TAG_enumeration_type": + return self.enum(type_name) + elif key == "DW_TAG_base_type": + return self.base_type(type_name) + elif key == "DW_TAG_typedef": + return self.typedef(type_name) + elif key == "DW_TAG_enumerator": + return self.enum_value(type_name) + else: + raise ValueError(f"Unsupported type: {key} {type_name}") + + return None + + def base_type(self, name): + base_types = self.types["DW_TAG_base_type"] + types = base_types.get_types(name) + if types is None: + return None + + for die in types: + name = die.attributes["DW_AT_name"].value.decode("utf-8") + size = die.attributes["DW_AT_byte_size"].value + + unsigned_map = { + 1: construct.Int8ul, + 2: construct.Int16ul, + 4: construct.Int32ul, + 8: construct.Int64ul, + } + signed_map = { + 1: construct.Int8sl, + 2: construct.Int16sl, + 4: construct.Int32sl, + 8: construct.Int64sl, + } + double_map = { + 2: construct.Float16l, + 4: construct.Float32l, + 8: construct.Float64l, + } + if "unsigned" in name: + return unsigned_map.get(size, None) + elif "double" in name or "float" in name: + return double_map.get(size, None) + elif "_Bool" in name: + return construct.Int8ul + elif "char" in name or "short" in name or "int" in name: + return signed_map.get(size, None) + + raise ValueError(f"Unsupported base type: {name}") + + def typedef(self, name): + typedefs = self.types["DW_TAG_typedef"] + types = typedefs.get_types(name) + if types is None: + return None + + for die in types: + name = die.attributes["DW_AT_name"].value.decode("utf-8") + type_attr = die.attributes["DW_AT_type"] + die = self.dwarf.get_DIE_from_refaddr(type_attr.value + die.cu.cu_offset) + return self.parse_die(die) + + def struct(self, type_name): + structs = self.types["DW_TAG_structure_type"] + types = structs.get_types(type_name) + + if types is None: + return None + + # If the type is a list, it means we have already obtained the enum value + ret = structs.get_result(type_name) + if ret is not None: + return ret + + rets = set() + for dies in types: + members = dict() + for die in dies.iter_children(): + member_name = die.attributes["DW_AT_name"].value.decode("utf-8") + member_type = die.attributes["DW_AT_type"].value + type_die = self.dwarf.get_DIE_from_refaddr( + member_type + die.cu.cu_offset + ) + member_type = self.parse_die(type_die) + members[member_name] = member_type + + struct = construct.Struct(**members) + if not rets or all(ret.sizeof() != struct.sizeof() for ret in rets): + rets.add(struct) + + return structs.set_result(type_name, rets) + + def enum(self, type_name): + if len(self.types.keys()) == 0: + self.parse_types() + + enums = self.types["DW_TAG_enumeration_type"] + types = enums.get_types(type_name) + + if types is None: + return None + + # If the type is a list, it means we have already obtained the enum value + ret = enums.get_result(type_name) + if ret is not None: + return ret + + rets = set() + for dies in types: + enum = dict() + for die in dies.iter_children(): + name = die.attributes["DW_AT_name"].value.decode("utf-8") + value = die.attributes["DW_AT_const_value"].value + enum[name] = value + + ret = IntEnum(type_name, enum) + + # Remove duplicates + if not any( + all(item[key] == value for key, value in enum.items()) for item in rets + ): + rets.add(ret) + + return enums.set_result(type_name, rets) + + def enum_value(self, enum_name): + if len(self.types.keys()) == 0: + self.parse_types() + + enums = self.types["DW_TAG_enumerator"] + types = enums.get_types(enum_name) + + if types is None: + return None + + ret = enums.get_result(enum_name) + if ret is not None: + return ret + + rets = set() + for dies in types: + name = dies.attributes["DW_AT_name"].value.decode("utf-8") + if name == enum_name: + value = dies.attributes["DW_AT_const_value"].value + rets.add(value) + + return enums.set_result(enum_name, rets) -- Gitee From be6aa8726140df8b684b3545c70d148dc5f7ba91 Mon Sep 17 00:00:00 2001 From: xuxingliang Date: Thu, 5 Dec 2024 15:42:20 +0800 Subject: [PATCH 041/235] nxgdb/mm: add prenode, nextnode property for mempool VELAPLATFO-48924 So it looks like a memory node in heap thus we can process it in a unified way Change-Id: I6c99d9bbbae167469ee73ec4f01201ae686f5c96 Signed-off-by: xuxingliang --- tools/pynuttx/nxgdb/mm.py | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/tools/pynuttx/nxgdb/mm.py b/tools/pynuttx/nxgdb/mm.py index d1e3ca42420..05b94e1eb00 100644 --- a/tools/pynuttx/nxgdb/mm.py +++ b/tools/pynuttx/nxgdb/mm.py @@ -128,6 +128,16 @@ class MemPoolBlock: ) return self._backtrace + @property + def prevnode(self) -> MemPoolBlock: + addr = self.address - self.nodesize + return MemPoolBlock(addr, self.blocksize, self.overhead) + + @property + def nextnode(self) -> MemPoolBlock: + addr = self.address + self.nodesize + return MemPoolBlock(addr, self.blocksize, self.overhead) + def read_memory(self) -> memoryview: return gdb.selected_inferior().read_memory(self.address, self.blocksize) -- Gitee From 7f156e7897b962bf0f6d2e5ac794188fd9e77336 Mon Sep 17 00:00:00 2001 From: xuxingliang Date: Fri, 6 Dec 2024 09:34:21 +0800 Subject: [PATCH 042/235] nxgdb: fix python3.8 compatability issue VELAPLATFO-48924 Change-Id: I412118831aa70383025787af7a5e618b2e3dd906 Signed-off-by: xuxingliang --- tools/pynuttx/nxgdb/circbuf.py | 4 ++-- tools/pynuttx/nxgdb/fs.py | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/tools/pynuttx/nxgdb/circbuf.py b/tools/pynuttx/nxgdb/circbuf.py index 3f0750ba4a7..3432fe471c5 100644 --- a/tools/pynuttx/nxgdb/circbuf.py +++ b/tools/pynuttx/nxgdb/circbuf.py @@ -21,7 +21,7 @@ ############################################################################ import argparse -from typing import Generator +from typing import Generator, Union import gdb @@ -31,7 +31,7 @@ from .protocols import circbuf as p class CircBuf(utils.Value, p.CircBuf): def __init__( - self, obj: gdb.Value | utils.Value, datatype: gdb.Type | None = None + self, obj: Union[gdb.Value, utils.Value], datatype: gdb.Type = None ) -> None: circbuf_s = utils.lookup_type("struct circbuf_s") if obj.type.code == gdb.TYPE_CODE_INT: diff --git a/tools/pynuttx/nxgdb/fs.py b/tools/pynuttx/nxgdb/fs.py index 4db3f25e132..79e71ccf156 100644 --- a/tools/pynuttx/nxgdb/fs.py +++ b/tools/pynuttx/nxgdb/fs.py @@ -22,7 +22,7 @@ import argparse import enum -from typing import Generator, Tuple +from typing import Generator, Tuple, Union import gdb @@ -73,7 +73,7 @@ class InodeType(enum.Enum): class Inode(utils.Value, p.Inode): - def __init__(self, obj: gdb.Value | utils.Value): + def __init__(self, obj: Union[gdb.Value, utils.Value]): super().__init__(obj) def __str__(self) -> str: -- Gitee From e311e021fecdd11ca1c4793896e049a492bf22f2 Mon Sep 17 00:00:00 2001 From: yinshengkai Date: Wed, 27 Nov 2024 21:24:50 +0800 Subject: [PATCH 043/235] tools/pynuttx: add trace python script VELAPLATFO-48894 Support converting sched_note data to perfetto trace format files Change-Id: I77c617c92beb884929a7d0cc44b90e6b90248bb4 Signed-off-by: yinshengkai --- tools/pynuttx/nxtrace/__init__.py | 19 + tools/pynuttx/nxtrace/perfetto_trace.py | 296 +++ tools/pynuttx/nxtrace/perfetto_trace_pb2.py | 2556 +++++++++++++++++++ tools/pynuttx/nxtrace/trace.py | 313 +++ tools/pynuttx/requirements.txt | 2 + tools/pynuttx/traceparse.py | 37 + 6 files changed, 3223 insertions(+) create mode 100644 tools/pynuttx/nxtrace/__init__.py create mode 100644 tools/pynuttx/nxtrace/perfetto_trace.py create mode 100644 tools/pynuttx/nxtrace/perfetto_trace_pb2.py create mode 100644 tools/pynuttx/nxtrace/trace.py create mode 100644 tools/pynuttx/traceparse.py diff --git a/tools/pynuttx/nxtrace/__init__.py b/tools/pynuttx/nxtrace/__init__.py new file mode 100644 index 00000000000..f99d3648bdd --- /dev/null +++ b/tools/pynuttx/nxtrace/__init__.py @@ -0,0 +1,19 @@ +############################################################################ +# tools/pynuttx/nxtrace/__init__.py +# +# Licensed to the Apache Software Foundation (ASF) under one or more +# contributor license agreements. See the NOTICE file distributed with +# this work for additional information regarding copyright ownership. The +# ASF licenses this file to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance with the +# License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# +############################################################################ diff --git a/tools/pynuttx/nxtrace/perfetto_trace.py b/tools/pynuttx/nxtrace/perfetto_trace.py new file mode 100644 index 00000000000..db299afe388 --- /dev/null +++ b/tools/pynuttx/nxtrace/perfetto_trace.py @@ -0,0 +1,296 @@ +############################################################################ +# tools/pynuttx/nxtrace/perfetto_trace.py +# +# Licensed to the Apache Software Foundation (ASF) under one or more +# contributor license agreements. See the NOTICE file distributed with +# this work for additional information regarding copyright ownership. The +# ASF licenses this file to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance with the +# License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# +############################################################################ + +import logging +from enum import IntEnum + +try: + from google.protobuf.message_factory import GetMessageClass +except ImportError: + print("Please execute the following command to install dependencies:") + print("pip install protobuf==4.25.3") + exit(1) + +from . import perfetto_trace_pb2 as pb2 + +logger = logging.getLogger(__name__) +logger.setLevel(logging.WARN) + + +class LogPriority: + UNSPECIFIED = pb2.AndroidLogPriority.PRIO_UNSPECIFIED + UNUSED = pb2.AndroidLogPriority.PRIO_UNUSED + VERBOSE = pb2.AndroidLogPriority.PRIO_VERBOSE + DEBUG = pb2.AndroidLogPriority.PRIO_DEBUG + INFO = pb2.AndroidLogPriority.PRIO_INFO + WARN = pb2.AndroidLogPriority.PRIO_WARN + ERROR = pb2.AndroidLogPriority.PRIO_ERROR + FATAL = pb2.AndroidLogPriority.PRIO_FATAL + + +class TaskState(IntEnum): + RUNNING = 0 + INTERRUPTIBLE = 1 + UNINTERRUPTIBLE = 2 + STOPPED = 4 + TRACED = 8 + DEAD = 16 + ZOMBIE = 32 + PARKED = 64 + INVALID = 128 + + +class TaskInfo: + def __init__(self, comm, pid, prio, tid=None): + self.pid = pid + self.comm = comm + self.prio = prio + self.tid = tid if tid is not None else pid + + +class TraceHead: + def __init__(self, ts, pid, cpu, tid=None): + self.ts = ts + self.pid = pid + self.cpu = cpu + self.tid = tid if tid is not None else pid + + +class TraceClassFactory: + def __new__(cls, message_name): + message_descriptor = cls._get_message_descriptor(message_name) + return GetMessageClass(message_descriptor) + + @classmethod + def _get_message_descriptor(cls, message_name): + """ + Recursively find the descriptor for nested messages. + """ + parts = message_name.split(".") + descriptor = pb2.DESCRIPTOR + + for part in parts: + # Handle FileDescriptor + if hasattr(descriptor, "message_types_by_name"): + if part not in descriptor.message_types_by_name: + raise ValueError(f"Message {message_name} not found in descriptor.") + descriptor = descriptor.message_types_by_name[part] + # Handle MessageDescriptor + elif hasattr(descriptor, "nested_types_by_name"): + if part not in descriptor.nested_types_by_name: + raise ValueError(f"Message {message_name} not found in descriptor.") + descriptor = descriptor.nested_types_by_name[part] + else: + raise ValueError(f"Invalid descriptor type for {message_name}") + return descriptor + + +class TraceInstanceFactory: + def __new__(cls, message_name, **kwargs): + # Get the message class + message_class = TraceClassFactory(message_name) + instance = message_class() + for field, value in kwargs.items(): + setattr(instance, field, value) + return instance + + +class PerfettoTrace: + def __init__(self, filename: str): + """Create a trace""" + self.flush_threshold = 10000 + + self.trace = pb2.Trace() + self.file = open(filename, "wb") + + def init(self): + # Initialize clock snapshots + clocks_class = TraceClassFactory("ClockSnapshot.Clock") + clocks = [clocks_class(clock_id=id, timestamp=0) for id in range(1, 7)] + + clock_snapshot = TraceInstanceFactory("ClockSnapshot") + clock_snapshot.primary_trace_clock = pb2.BUILTIN_CLOCK_BOOTTIME + clock_snapshot.clocks.extend(clocks) + + pkt = TraceInstanceFactory("TracePacket", trusted_packet_sequence_id=1) + pkt.clock_snapshot.CopyFrom(clock_snapshot) + self.trace.packet.append(pkt) + + # Configure trace packets + pkt = self.trace.packet.add(trusted_packet_sequence_id=1) + pkt.trace_config.buffers.add().size_kb = 1024 + pkt.trace_config.data_sources.add().config.name = "track_event" + + pkt = self.trace.packet.add(trusted_packet_sequence_id=2, sequence_flags=1) + pkt.trace_packet_defaults.track_event_defaults.track_uuid = 1 + pkt.trace_packet_defaults.timestamp_clock_id = 1 + + pkt = self.trace.packet.add() + pkt.trusted_packet_sequence_id = 1 + pkt.trace_config.buffers.add().size_kb = 1024 + pkt.trace_config.data_sources.add().config.name = "track_event" + + pkt = self.trace.packet.add() + pkt.trusted_packet_sequence_id = 2 + pkt.trace_packet_defaults.track_event_defaults.track_uuid = 1 + pkt.trace_packet_defaults.timestamp_clock_id = 1 + pkt.sequence_flags = 1 + + def flush(self): + """Flush trace. This creates a perfetto trace packet and writes to disk.""" + self.file.write(self.trace.SerializeToString()) + self.file.flush() + self.trace = pb2.Trace() + + def __del__(self): + self.flush() + self.file.close() + + # Ftrace common events API + + def log(self, ts, tag, pid, tid=None, prio=LogPriority.INFO, msg="", args=None): + tid = tid if tid is not None else pid + pkt = self.trace.packet.add() + + log_event = TraceInstanceFactory( + "AndroidLogPacket.LogEvent", + timestamp=ts, + log_id=pb2.AndroidLogId.LID_DEFAULT, + pid=pid, + tid=tid, + uid=0, + tag=tag, + prio=prio, + message=msg, + ) + pkt.android_log.events.append(log_event) + logger.debug(pkt) + + def ftrace_event(self, head: TraceHead, event): + pkt = self.trace.packet.add() + ftrace_events = TraceInstanceFactory("FtraceEventBundle", cpu=head.cpu) + events = TraceInstanceFactory("FtraceEvent", pid=head.pid, timestamp=head.ts) + + event_descriptor = event.DESCRIPTOR + + for oneof in events.DESCRIPTOR.oneofs: + for field in oneof.fields: + if field.message_type == event_descriptor: + getattr(events, field.name).CopyFrom(event) + break + + ftrace_events.event.append(events) + pkt.ftrace_events.CopyFrom(ftrace_events) + logger.debug(pkt) + return pkt + + # Ftrace events API + + def sched_wakeup_new(self, head: TraceHead, task: TaskInfo): + wakeup = TraceInstanceFactory( + "SchedWakeupNewFtraceEvent", + pid=task.pid, + comm=task.comm, + prio=task.prio, + target_cpu=head.cpu, + ) + return self.ftrace_event(head, wakeup) + + def sched_waking(self, head: TraceHead, task: TaskInfo): + waking = TraceInstanceFactory( + "SchedWakingFtraceEvent", + pid=task.pid, + comm=task.comm, + prio=task.prio, + target_cpu=head.cpu, + ) + return self.ftrace_event(head, waking) + + def sched_wakeup(self, head: TraceHead, task: TaskInfo): + wakeup = TraceInstanceFactory( + "SchedWakeupFtraceEvent", + pid=task.pid, + comm=task.comm, + prio=task.prio, + target_cpu=head.cpu, + ) + return self.ftrace_event(head, wakeup) + + def sched_switch( + self, + head: TraceHead, + prev_state=0, + task_prev: TaskInfo = None, + task_next: TaskInfo = None, + ): + switch = pb2.SchedSwitchFtraceEvent( + prev_comm=task_prev.comm, + prev_pid=task_prev.pid, + prev_prio=task_prev.prio, + prev_state=prev_state, + next_comm=task_next.comm, + next_pid=task_next.pid, + next_prio=task_next.prio, + ) + + return self.ftrace_event(head, switch) + + def irq_entry(self, head: TraceHead, irq: int, name: str, handler: int): + irq_entry = TraceInstanceFactory( + "IrqHandlerEntryFtraceEvent", irq=irq, name=name, handler=handler + ) + return self.ftrace_event(head, irq_entry) + + def irq_exit(self, head: TraceHead, irq, ret=0): + irq_exit = TraceInstanceFactory("IrqHandlerExitFtraceEvent", irq=irq, ret=ret) + return self.ftrace_event(head, irq_exit) + + def print(self, head: TraceHead, buf=None): + print_event = TraceInstanceFactory("PrintFtraceEvent", buf=buf) + return self.ftrace_event(head, print_event) + + # Atrace events API + + def atrace_begin(self, head: TraceHead, msg): + return self.print(head, f"B|{head.pid}|{msg}") + + def atrace_end(self, head: TraceHead): + return self.print(head, "E") + + def atrace_async_begin(self, head: TraceHead, msg, cookie): + return self.print(head, f"S|{head.pid}|{msg}|{cookie}") + + def atrace_async_end(self, head: TraceHead, msg, cookie): + return self.print(head, f"F|{head.pid}|{msg}|{cookie}") + + def atrace_async_for_track_begin(self, head: TraceHead, track_name, msg, cookie): + return self.print(head, f"G|{head.pid}|{track_name}|{msg}|{cookie}") + + def atrace_async_for_track_end(self, head: TraceHead, track_name, msg, cookie): + return self.print(head, f"H|{head.pid}|{track_name}|{msg}|{cookie}") + + def atrace_instant(self, head: TraceHead, msg): + return self.print(head, f"I|{head.pid}|{msg}") + + def atrace_instant_for_track(self, head: TraceHead, track_name, msg): + return self.print(head, f"N|{head.pid}|{track_name}|{msg}") + + def atrace_int(self, head: TraceHead, msg, value): + return self.print(head, f"C|{head.pid}|{msg}|{value}") diff --git a/tools/pynuttx/nxtrace/perfetto_trace_pb2.py b/tools/pynuttx/nxtrace/perfetto_trace_pb2.py new file mode 100644 index 00000000000..e7edc7c6b15 --- /dev/null +++ b/tools/pynuttx/nxtrace/perfetto_trace_pb2.py @@ -0,0 +1,2556 @@ +# -*- coding: utf-8 -*- +# Generated by the protocol buffer compiler. DO NOT EDIT! +# source: perfetto_trace.proto +# Protobuf Python Version: 4.25.3 +"""Generated protocol buffer code.""" +from google.protobuf import descriptor as _descriptor +from google.protobuf import descriptor_pool as _descriptor_pool +from google.protobuf import symbol_database as _symbol_database +from google.protobuf.internal import builder as _builder + +# @@protoc_insertion_point(imports) + +_sym_db = _symbol_database.Default() + + +DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile( + b'\n\x14perfetto_trace.proto\x12\x0fperfetto.protos"\x94\x01\n\x10\x46traceDescriptor\x12K\n\x11\x61trace_categories\x18\x01 \x03(\x0b\x32\x30.perfetto.protos.FtraceDescriptor.AtraceCategory\x1a\x33\n\x0e\x41traceCategory\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x13\n\x0b\x64\x65scription\x18\x02 \x01(\t"\xb6\x0b\n\x14GpuCounterDescriptor\x12\x43\n\x05specs\x18\x01 \x03(\x0b\x32\x34.perfetto.protos.GpuCounterDescriptor.GpuCounterSpec\x12\x45\n\x06\x62locks\x18\x02 \x03(\x0b\x32\x35.perfetto.protos.GpuCounterDescriptor.GpuCounterBlock\x12\x1e\n\x16min_sampling_period_ns\x18\x03 \x01(\x04\x12\x1e\n\x16max_sampling_period_ns\x18\x04 \x01(\x04\x12&\n\x1esupports_instrumented_sampling\x18\x05 \x01(\x08\x1a\x8e\x03\n\x0eGpuCounterSpec\x12\x12\n\ncounter_id\x18\x01 \x01(\r\x12\x0c\n\x04name\x18\x02 \x01(\t\x12\x13\n\x0b\x64\x65scription\x18\x03 \x01(\t\x12\x18\n\x0eint_peak_value\x18\x05 \x01(\x03H\x00\x12\x1b\n\x11\x64ouble_peak_value\x18\x06 \x01(\x01H\x00\x12J\n\x0fnumerator_units\x18\x07 \x03(\x0e\x32\x31.perfetto.protos.GpuCounterDescriptor.MeasureUnit\x12L\n\x11\x64\x65nominator_units\x18\x08 \x03(\x0e\x32\x31.perfetto.protos.GpuCounterDescriptor.MeasureUnit\x12\x19\n\x11select_by_default\x18\t \x01(\x08\x12\x45\n\x06groups\x18\n \x03(\x0e\x32\x35.perfetto.protos.GpuCounterDescriptor.GpuCounterGroupB\x0c\n\npeak_valueJ\x04\x08\x04\x10\x05\x1as\n\x0fGpuCounterBlock\x12\x10\n\x08\x62lock_id\x18\x01 \x01(\r\x12\x16\n\x0e\x62lock_capacity\x18\x02 \x01(\r\x12\x0c\n\x04name\x18\x03 \x01(\t\x12\x13\n\x0b\x64\x65scription\x18\x04 \x01(\t\x12\x13\n\x0b\x63ounter_ids\x18\x05 \x03(\r"u\n\x0fGpuCounterGroup\x12\x10\n\x0cUNCLASSIFIED\x10\x00\x12\n\n\x06SYSTEM\x10\x01\x12\x0c\n\x08VERTICES\x10\x02\x12\r\n\tFRAGMENTS\x10\x03\x12\x0e\n\nPRIMITIVES\x10\x04\x12\n\n\x06MEMORY\x10\x05\x12\x0b\n\x07\x43OMPUTE\x10\x06"\xac\x04\n\x0bMeasureUnit\x12\x08\n\x04NONE\x10\x00\x12\x07\n\x03\x42IT\x10\x01\x12\x0b\n\x07KILOBIT\x10\x02\x12\x0b\n\x07MEGABIT\x10\x03\x12\x0b\n\x07GIGABIT\x10\x04\x12\x0b\n\x07TERABIT\x10\x05\x12\x0b\n\x07PETABIT\x10\x06\x12\x08\n\x04\x42YTE\x10\x07\x12\x0c\n\x08KILOBYTE\x10\x08\x12\x0c\n\x08MEGABYTE\x10\t\x12\x0c\n\x08GIGABYTE\x10\n\x12\x0c\n\x08TERABYTE\x10\x0b\x12\x0c\n\x08PETABYTE\x10\x0c\x12\t\n\x05HERTZ\x10\r\x12\r\n\tKILOHERTZ\x10\x0e\x12\r\n\tMEGAHERTZ\x10\x0f\x12\r\n\tGIGAHERTZ\x10\x10\x12\r\n\tTERAHERTZ\x10\x11\x12\r\n\tPETAHERTZ\x10\x12\x12\x0e\n\nNANOSECOND\x10\x13\x12\x0f\n\x0bMICROSECOND\x10\x14\x12\x0f\n\x0bMILLISECOND\x10\x15\x12\n\n\x06SECOND\x10\x16\x12\n\n\x06MINUTE\x10\x17\x12\x08\n\x04HOUR\x10\x18\x12\n\n\x06VERTEX\x10\x19\x12\t\n\x05PIXEL\x10\x1a\x12\x0c\n\x08TRIANGLE\x10\x1b\x12\r\n\tPRIMITIVE\x10&\x12\x0c\n\x08\x46RAGMENT\x10\'\x12\r\n\tMILLIWATT\x10\x1c\x12\x08\n\x04WATT\x10\x1d\x12\x0c\n\x08KILOWATT\x10\x1e\x12\t\n\x05JOULE\x10\x1f\x12\x08\n\x04VOLT\x10 \x12\n\n\x06\x41MPERE\x10!\x12\x0b\n\x07\x43\x45LSIUS\x10"\x12\x0e\n\nFAHRENHEIT\x10#\x12\n\n\x06KELVIN\x10$\x12\x0b\n\x07PERCENT\x10%\x12\x0f\n\x0bINSTRUCTION\x10("E\n\x12TrackEventCategory\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x13\n\x0b\x64\x65scription\x18\x02 \x01(\t\x12\x0c\n\x04tags\x18\x03 \x03(\t"Y\n\x14TrackEventDescriptor\x12\x41\n\x14\x61vailable_categories\x18\x01 \x03(\x0b\x32#.perfetto.protos.TrackEventCategory"\xfe\x02\n\x14\x44\x61taSourceDescriptor\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\n\n\x02id\x18\x07 \x01(\x04\x12\x1b\n\x13will_notify_on_stop\x18\x02 \x01(\x08\x12\x1c\n\x14will_notify_on_start\x18\x03 \x01(\x08\x12\'\n\x1fhandles_incremental_state_clear\x18\x04 \x01(\x08\x12\x10\n\x08no_flush\x18\t \x01(\x08\x12I\n\x16gpu_counter_descriptor\x18\x05 \x01(\x0b\x32%.perfetto.protos.GpuCounterDescriptorB\x02(\x01\x12I\n\x16track_event_descriptor\x18\x06 \x01(\x0b\x32%.perfetto.protos.TrackEventDescriptorB\x02(\x01\x12@\n\x11\x66trace_descriptor\x18\x08 \x01(\x0b\x32!.perfetto.protos.FtraceDescriptorB\x02(\x01"\xa7\x06\n\x13TracingServiceState\x12@\n\tproducers\x18\x01 \x03(\x0b\x32-.perfetto.protos.TracingServiceState.Producer\x12\x45\n\x0c\x64\x61ta_sources\x18\x02 \x03(\x0b\x32/.perfetto.protos.TracingServiceState.DataSource\x12M\n\x10tracing_sessions\x18\x06 \x03(\x0b\x32\x33.perfetto.protos.TracingServiceState.TracingSession\x12!\n\x19supports_tracing_sessions\x18\x07 \x01(\x08\x12\x14\n\x0cnum_sessions\x18\x03 \x01(\x05\x12\x1c\n\x14num_sessions_started\x18\x04 \x01(\x05\x12\x1f\n\x17tracing_service_version\x18\x05 \x01(\t\x1aS\n\x08Producer\x12\n\n\x02id\x18\x01 \x01(\x05\x12\x0c\n\x04name\x18\x02 \x01(\t\x12\x0b\n\x03pid\x18\x05 \x01(\x05\x12\x0b\n\x03uid\x18\x03 \x01(\x05\x12\x13\n\x0bsdk_version\x18\x04 \x01(\t\x1a_\n\nDataSource\x12<\n\rds_descriptor\x18\x01 \x01(\x0b\x32%.perfetto.protos.DataSourceDescriptor\x12\x13\n\x0bproducer_id\x18\x02 \x01(\x05\x1a\x89\x02\n\x0eTracingSession\x12\n\n\x02id\x18\x01 \x01(\x04\x12\x14\n\x0c\x63onsumer_uid\x18\x02 \x01(\x05\x12\r\n\x05state\x18\x03 \x01(\t\x12\x1b\n\x13unique_session_name\x18\x04 \x01(\t\x12\x16\n\x0e\x62uffer_size_kb\x18\x05 \x03(\r\x12\x13\n\x0b\x64uration_ms\x18\x06 \x01(\r\x12\x18\n\x10num_data_sources\x18\x07 \x01(\r\x12\x19\n\x11start_realtime_ns\x18\x08 \x01(\x03\x12\x17\n\x0f\x62ugreport_score\x18\t \x01(\x05\x12\x1a\n\x12\x62ugreport_filename\x18\n \x01(\t\x12\x12\n\nis_started\x18\x0b \x01(\x08"@\n!AndroidGameInterventionListConfig\x12\x1b\n\x13package_name_filter\x18\x01 \x03(\t"\xd3\x04\n\x17\x41ndroidInputEventConfig\x12@\n\x04mode\x18\x01 \x01(\x0e\x32\x32.perfetto.protos.AndroidInputEventConfig.TraceMode\x12\x41\n\x05rules\x18\x02 \x03(\x0b\x32\x32.perfetto.protos.AndroidInputEventConfig.TraceRule\x12%\n\x1dtrace_dispatcher_input_events\x18\x03 \x01(\x08\x12(\n trace_dispatcher_window_dispatch\x18\x04 \x01(\x08\x1a\xc8\x01\n\tTraceRule\x12H\n\x0btrace_level\x18\x01 \x01(\x0e\x32\x33.perfetto.protos.AndroidInputEventConfig.TraceLevel\x12\x1a\n\x12match_all_packages\x18\x02 \x03(\t\x12\x1a\n\x12match_any_packages\x18\x03 \x03(\t\x12\x14\n\x0cmatch_secure\x18\x04 \x01(\x08\x12#\n\x1bmatch_ime_connection_active\x18\x05 \x01(\x08"?\n\tTraceMode\x12\x18\n\x14TRACE_MODE_TRACE_ALL\x10\x00\x12\x18\n\x14TRACE_MODE_USE_RULES\x10\x01"V\n\nTraceLevel\x12\x14\n\x10TRACE_LEVEL_NONE\x10\x00\x12\x18\n\x14TRACE_LEVEL_REDACTED\x10\x01\x12\x18\n\x14TRACE_LEVEL_COMPLETE\x10\x02"\x94\x01\n\x10\x41ndroidLogConfig\x12.\n\x07log_ids\x18\x01 \x03(\x0e\x32\x1d.perfetto.protos.AndroidLogId\x12\x35\n\x08min_prio\x18\x03 \x01(\x0e\x32#.perfetto.protos.AndroidLogPriority\x12\x13\n\x0b\x66ilter_tags\x18\x04 \x03(\tJ\x04\x08\x02\x10\x03"+\n\x18\x41ndroidPolledStateConfig\x12\x0f\n\x07poll_ms\x18\x01 \x01(\r"\x8a\x01\n\x1c\x41ndroidSdkSyspropGuardConfig\x12(\n surfaceflinger_skia_track_events\x18\x01 \x01(\x08\x12\x1e\n\x16hwui_skia_track_events\x18\x02 \x01(\x08\x12 \n\x18hwui_package_name_filter\x18\x03 \x03(\t"E\n\x1b\x41ndroidSystemPropertyConfig\x12\x0f\n\x07poll_ms\x18\x01 \x01(\r\x12\x15\n\rproperty_name\x18\x02 \x03(\t"\xab\x01\n\x18NetworkPacketTraceConfig\x12\x0f\n\x07poll_ms\x18\x01 \x01(\r\x12\x1d\n\x15\x61ggregation_threshold\x18\x02 \x01(\r\x12\x14\n\x0cintern_limit\x18\x03 \x01(\r\x12\x17\n\x0f\x64rop_local_port\x18\x04 \x01(\x08\x12\x18\n\x10\x64rop_remote_port\x18\x05 \x01(\x08\x12\x16\n\x0e\x64rop_tcp_flags\x18\x06 \x01(\x08"1\n\x12PackagesListConfig\x12\x1b\n\x13package_name_filter\x18\x01 \x03(\t"\x84\x02\n\x10PixelModemConfig\x12\x41\n\x0b\x65vent_group\x18\x01 \x01(\x0e\x32,.perfetto.protos.PixelModemConfig.EventGroup\x12\x1f\n\x17pigweed_hash_allow_list\x18\x02 \x03(\x03\x12\x1e\n\x16pigweed_hash_deny_list\x18\x03 \x03(\x03"l\n\nEventGroup\x12\x17\n\x13\x45VENT_GROUP_UNKNOWN\x10\x00\x12\x1d\n\x19\x45VENT_GROUP_LOW_BANDWIDTH\x10\x01\x12&\n"EVENT_GROUP_HIGH_AND_LOW_BANDWIDTH\x10\x02"\xf8\x01\n\x0eProtoLogConfig\x12\x37\n\x0fgroup_overrides\x18\x01 \x03(\x0b\x32\x1e.perfetto.protos.ProtoLogGroup\x12\x41\n\x0ctracing_mode\x18\x02 \x01(\x0e\x32+.perfetto.protos.ProtoLogConfig.TracingMode\x12>\n\x16\x64\x65\x66\x61ult_log_from_level\x18\x03 \x01(\x0e\x32\x1e.perfetto.protos.ProtoLogLevel"*\n\x0bTracingMode\x12\x0b\n\x07\x44\x45\x46\x41ULT\x10\x00\x12\x0e\n\nENABLE_ALL\x10\x01"q\n\rProtoLogGroup\x12\x12\n\ngroup_name\x18\x01 \x01(\t\x12\x30\n\x08log_from\x18\x02 \x01(\x0e\x32\x1e.perfetto.protos.ProtoLogLevel\x12\x1a\n\x12\x63ollect_stacktrace\x18\x03 \x01(\x08"\xf0\x03\n\x1aSurfaceFlingerLayersConfig\x12>\n\x04mode\x18\x01 \x01(\x0e\x32\x30.perfetto.protos.SurfaceFlingerLayersConfig.Mode\x12J\n\x0btrace_flags\x18\x02 \x03(\x0e\x32\x35.perfetto.protos.SurfaceFlingerLayersConfig.TraceFlag"s\n\x04Mode\x12\x14\n\x10MODE_UNSPECIFIED\x10\x00\x12\x0f\n\x0bMODE_ACTIVE\x10\x01\x12\x12\n\x0eMODE_GENERATED\x10\x02\x12\r\n\tMODE_DUMP\x10\x03\x12!\n\x1dMODE_GENERATED_BUGREPORT_ONLY\x10\x04"\xd0\x01\n\tTraceFlag\x12\x1a\n\x16TRACE_FLAG_UNSPECIFIED\x10\x00\x12\x14\n\x10TRACE_FLAG_INPUT\x10\x02\x12\x1a\n\x16TRACE_FLAG_COMPOSITION\x10\x04\x12\x14\n\x10TRACE_FLAG_EXTRA\x10\x08\x12\x12\n\x0eTRACE_FLAG_HWC\x10\x10\x12\x16\n\x12TRACE_FLAG_BUFFERS\x10 \x12\x1f\n\x1bTRACE_FLAG_VIRTUAL_DISPLAYS\x10@\x12\x12\n\x0eTRACE_FLAG_ALL\x10\x0e"\xac\x01\n SurfaceFlingerTransactionsConfig\x12\x44\n\x04mode\x18\x01 \x01(\x0e\x32\x36.perfetto.protos.SurfaceFlingerTransactionsConfig.Mode"B\n\x04Mode\x12\x14\n\x10MODE_UNSPECIFIED\x10\x00\x12\x13\n\x0fMODE_CONTINUOUS\x10\x01\x12\x0f\n\x0bMODE_ACTIVE\x10\x02"\x93\x03\n\x13WindowManagerConfig\x12H\n\rlog_frequency\x18\x01 \x01(\x0e\x32\x31.perfetto.protos.WindowManagerConfig.LogFrequency\x12@\n\tlog_level\x18\x02 \x01(\x0e\x32-.perfetto.protos.WindowManagerConfig.LogLevel"\x84\x01\n\x0cLogFrequency\x12\x1d\n\x19LOG_FREQUENCY_UNSPECIFIED\x10\x00\x12\x17\n\x13LOG_FREQUENCY_FRAME\x10\x01\x12\x1d\n\x19LOG_FREQUENCY_TRANSACTION\x10\x02\x12\x1d\n\x19LOG_FREQUENCY_SINGLE_DUMP\x10\x03"i\n\x08LogLevel\x12\x19\n\x15LOG_LEVEL_UNSPECIFIED\x10\x00\x12\x15\n\x11LOG_LEVEL_VERBOSE\x10\x01\x12\x13\n\x0fLOG_LEVEL_DEBUG\x10\x02\x12\x16\n\x12LOG_LEVEL_CRITICAL\x10\x03"\x92\x02\n\x0c\x43hromeConfig\x12\x14\n\x0ctrace_config\x18\x01 \x01(\t\x12!\n\x19privacy_filtering_enabled\x18\x02 \x01(\x08\x12\x1e\n\x16\x63onvert_to_legacy_json\x18\x03 \x01(\x08\x12\x45\n\x0f\x63lient_priority\x18\x04 \x01(\x0e\x32,.perfetto.protos.ChromeConfig.ClientPriority\x12\x1f\n\x17json_agent_label_filter\x18\x05 \x01(\t"A\n\x0e\x43lientPriority\x12\x0b\n\x07UNKNOWN\x10\x00\x12\x0e\n\nBACKGROUND\x10\x01\x12\x12\n\x0eUSER_INITIATED\x10\x02"@\n\x08V8Config\x12\x1a\n\x12log_script_sources\x18\x01 \x01(\x08\x12\x18\n\x10log_instructions\x18\x02 \x01(\x08"s\n\tEtwConfig\x12;\n\x0ckernel_flags\x18\x01 \x03(\x0e\x32%.perfetto.protos.EtwConfig.KernelFlag")\n\nKernelFlag\x12\x0b\n\x07\x43SWITCH\x10\x00\x12\x0e\n\nDISPATCHER\x10\x01"\x92\t\n\x0c\x46traceConfig\x12\x15\n\rftrace_events\x18\x01 \x03(\t\x12\x19\n\x11\x61trace_categories\x18\x02 \x03(\t\x12\x13\n\x0b\x61trace_apps\x18\x03 \x03(\t\x12$\n\x1c\x61trace_categories_prefer_sdk\x18\x1c \x03(\t\x12\x16\n\x0e\x62uffer_size_kb\x18\n \x01(\r\x12\x17\n\x0f\x64rain_period_ms\x18\x0b \x01(\r\x12\x1c\n\x14\x64rain_buffer_percent\x18\x1a \x01(\r\x12G\n\rcompact_sched\x18\x0c \x01(\x0b\x32\x30.perfetto.protos.FtraceConfig.CompactSchedConfig\x12?\n\x0cprint_filter\x18\x16 \x01(\x0b\x32).perfetto.protos.FtraceConfig.PrintFilter\x12\x17\n\x0fsymbolize_ksyms\x18\r \x01(\x08\x12\x46\n\x10ksyms_mem_policy\x18\x11 \x01(\x0e\x32,.perfetto.protos.FtraceConfig.KsymsMemPolicy\x12\x36\n*initialize_ksyms_synchronously_for_testing\x18\x0e \x01(\x08\x42\x02\x18\x01\x12\x19\n\x11throttle_rss_stat\x18\x0f \x01(\x08\x12\x1e\n\x16\x64isable_generic_events\x18\x10 \x01(\x08\x12\x16\n\x0esyscall_events\x18\x12 \x03(\t\x12\x1d\n\x15\x65nable_function_graph\x18\x13 \x01(\x08\x12\x18\n\x10\x66unction_filters\x18\x14 \x03(\t\x12\x1c\n\x14\x66unction_graph_roots\x18\x15 \x03(\t\x12\x1e\n\x16preserve_ftrace_buffer\x18\x17 \x01(\x08\x12\x1f\n\x17use_monotonic_raw_clock\x18\x18 \x01(\x08\x12\x15\n\rinstance_name\x18\x19 \x01(\t\x12\x1f\n\x17\x62uffer_size_lower_bound\x18\x1b \x01(\x08\x1a%\n\x12\x43ompactSchedConfig\x12\x0f\n\x07\x65nabled\x18\x01 \x01(\x08\x1a\x82\x02\n\x0bPrintFilter\x12=\n\x05rules\x18\x01 \x03(\x0b\x32..perfetto.protos.FtraceConfig.PrintFilter.Rule\x1a\xb3\x01\n\x04Rule\x12\x10\n\x06prefix\x18\x01 \x01(\tH\x00\x12R\n\natrace_msg\x18\x03 \x01(\x0b\x32<.perfetto.protos.FtraceConfig.PrintFilter.Rule.AtraceMessageH\x00\x12\r\n\x05\x61llow\x18\x02 \x01(\x08\x1a-\n\rAtraceMessage\x12\x0c\n\x04type\x18\x01 \x01(\t\x12\x0e\n\x06prefix\x18\x02 \x01(\tB\x07\n\x05match"T\n\x0eKsymsMemPolicy\x12\x15\n\x11KSYMS_UNSPECIFIED\x10\x00\x12\x19\n\x15KSYMS_CLEANUP_ON_STOP\x10\x01\x12\x10\n\x0cKSYMS_RETAIN\x10\x02"x\n\x10GpuCounterConfig\x12\x19\n\x11\x63ounter_period_ns\x18\x01 \x01(\x04\x12\x13\n\x0b\x63ounter_ids\x18\x02 \x03(\r\x12\x1d\n\x15instrumented_sampling\x18\x03 \x01(\x08\x12\x15\n\rfix_gpu_clock\x18\x04 \x01(\x08"Z\n\x12VulkanMemoryConfig\x12!\n\x19track_driver_memory_usage\x18\x01 \x01(\x08\x12!\n\x19track_device_memory_usage\x18\x02 \x01(\x08"\xa3\x02\n\x0fInodeFileConfig\x12\x18\n\x10scan_interval_ms\x18\x01 \x01(\r\x12\x15\n\rscan_delay_ms\x18\x02 \x01(\r\x12\x17\n\x0fscan_batch_size\x18\x03 \x01(\r\x12\x13\n\x0b\x64o_not_scan\x18\x04 \x01(\x08\x12\x19\n\x11scan_mount_points\x18\x05 \x03(\t\x12T\n\x13mount_point_mapping\x18\x06 \x03(\x0b\x32\x37.perfetto.protos.InodeFileConfig.MountPointMappingEntry\x1a@\n\x16MountPointMappingEntry\x12\x12\n\nmountpoint\x18\x01 \x01(\t\x12\x12\n\nscan_roots\x18\x02 \x03(\t"\xa5\x01\n\rConsoleConfig\x12\x35\n\x06output\x18\x01 \x01(\x0e\x32%.perfetto.protos.ConsoleConfig.Output\x12\x15\n\renable_colors\x18\x02 \x01(\x08"F\n\x06Output\x12\x16\n\x12OUTPUT_UNSPECIFIED\x10\x00\x12\x11\n\rOUTPUT_STDOUT\x10\x01\x12\x11\n\rOUTPUT_STDERR\x10\x02"Y\n\x11InterceptorConfig\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x36\n\x0e\x63onsole_config\x18\x64 \x01(\x0b\x32\x1e.perfetto.protos.ConsoleConfig"\xc0\x03\n\x12\x41ndroidPowerConfig\x12\x17\n\x0f\x62\x61ttery_poll_ms\x18\x01 \x01(\r\x12M\n\x10\x62\x61ttery_counters\x18\x02 \x03(\x0e\x32\x33.perfetto.protos.AndroidPowerConfig.BatteryCounters\x12\x1b\n\x13\x63ollect_power_rails\x18\x03 \x01(\x08\x12+\n#collect_energy_estimation_breakdown\x18\x04 \x01(\x08\x12&\n\x1e\x63ollect_entity_state_residency\x18\x05 \x01(\x08"\xcf\x01\n\x0f\x42\x61tteryCounters\x12\x1f\n\x1b\x42\x41TTERY_COUNTER_UNSPECIFIED\x10\x00\x12\x1a\n\x16\x42\x41TTERY_COUNTER_CHARGE\x10\x01\x12$\n BATTERY_COUNTER_CAPACITY_PERCENT\x10\x02\x12\x1b\n\x17\x42\x41TTERY_COUNTER_CURRENT\x10\x03\x12\x1f\n\x1b\x42\x41TTERY_COUNTER_CURRENT_AVG\x10\x04\x12\x1b\n\x17\x42\x41TTERY_COUNTER_VOLTAGE\x10\x05"\xa6\x03\n\x12ProcessStatsConfig\x12:\n\x06quirks\x18\x01 \x03(\x0e\x32*.perfetto.protos.ProcessStatsConfig.Quirks\x12#\n\x1bscan_all_processes_on_start\x18\x02 \x01(\x08\x12\x1b\n\x13record_thread_names\x18\x03 \x01(\x08\x12\x1a\n\x12proc_stats_poll_ms\x18\x04 \x01(\r\x12\x1f\n\x17proc_stats_cache_ttl_ms\x18\x06 \x01(\r\x12\x1b\n\x13resolve_process_fds\x18\t \x01(\x08\x12\x19\n\x11scan_smaps_rollup\x18\n \x01(\x08\x12\x1a\n\x12record_process_age\x18\x0b \x01(\x08\x12\x1e\n\x16record_process_runtime\x18\x0c \x01(\x08"U\n\x06Quirks\x12\x16\n\x12QUIRKS_UNSPECIFIED\x10\x00\x12\x1c\n\x14\x44ISABLE_INITIAL_DUMP\x10\x01\x1a\x02\x08\x01\x12\x15\n\x11\x44ISABLE_ON_DEMAND\x10\x02J\x04\x08\x07\x10\x08J\x04\x08\x08\x10\t"\xcc\x06\n\x0fHeapprofdConfig\x12\x1f\n\x17sampling_interval_bytes\x18\x01 \x01(\x04\x12)\n!adaptive_sampling_shmem_threshold\x18\x18 \x01(\x04\x12\x35\n-adaptive_sampling_max_sampling_interval_bytes\x18\x19 \x01(\x04\x12\x17\n\x0fprocess_cmdline\x18\x02 \x03(\t\x12\x0b\n\x03pid\x18\x04 \x03(\x04\x12\x1b\n\x13target_installed_by\x18\x1a \x03(\t\x12\r\n\x05heaps\x18\x14 \x03(\t\x12\x15\n\rexclude_heaps\x18\x1b \x03(\t\x12\x1a\n\x12stream_allocations\x18\x17 \x01(\x08\x12\x1f\n\x17heap_sampling_intervals\x18\x16 \x03(\x04\x12\x11\n\tall_heaps\x18\x15 \x01(\x08\x12\x0b\n\x03\x61ll\x18\x05 \x01(\x08\x12\x1f\n\x17min_anonymous_memory_kb\x18\x0f \x01(\r\x12\x1f\n\x17max_heapprofd_memory_kb\x18\x10 \x01(\r\x12\x1e\n\x16max_heapprofd_cpu_secs\x18\x11 \x01(\x04\x12\x1a\n\x12skip_symbol_prefix\x18\x07 \x03(\t\x12U\n\x16\x63ontinuous_dump_config\x18\x06 \x01(\x0b\x32\x35.perfetto.protos.HeapprofdConfig.ContinuousDumpConfig\x12\x18\n\x10shmem_size_bytes\x18\x08 \x01(\x04\x12\x14\n\x0c\x62lock_client\x18\t \x01(\x08\x12\x1f\n\x17\x62lock_client_timeout_us\x18\x0e \x01(\r\x12\x12\n\nno_startup\x18\n \x01(\x08\x12\x12\n\nno_running\x18\x0b \x01(\x08\x12\x13\n\x0b\x64ump_at_max\x18\r \x01(\x08\x12\x1d\n\x15\x64isable_fork_teardown\x18\x12 \x01(\x08\x12\x1f\n\x17\x64isable_vfork_detection\x18\x13 \x01(\x08\x1aG\n\x14\x43ontinuousDumpConfig\x12\x15\n\rdump_phase_ms\x18\x05 \x01(\r\x12\x18\n\x10\x64ump_interval_ms\x18\x06 \x01(\rJ\x04\x08\x0c\x10\r"\xe1\x02\n\x0fJavaHprofConfig\x12\x17\n\x0fprocess_cmdline\x18\x01 \x03(\t\x12\x0b\n\x03pid\x18\x02 \x03(\x04\x12\x1b\n\x13target_installed_by\x18\x07 \x03(\t\x12U\n\x16\x63ontinuous_dump_config\x18\x03 \x01(\x0b\x32\x35.perfetto.protos.JavaHprofConfig.ContinuousDumpConfig\x12\x1f\n\x17min_anonymous_memory_kb\x18\x04 \x01(\r\x12\x12\n\ndump_smaps\x18\x05 \x01(\x08\x12\x15\n\rignored_types\x18\x06 \x03(\t\x1ah\n\x14\x43ontinuousDumpConfig\x12\x15\n\rdump_phase_ms\x18\x01 \x01(\r\x12\x18\n\x10\x64ump_interval_ms\x18\x02 \x01(\r\x12\x1f\n\x17scan_pids_only_on_start\x18\x03 \x01(\x08"\xc7\x08\n\nPerfEvents\x1a\xc5\x02\n\x08Timebase\x12\x13\n\tfrequency\x18\x02 \x01(\x04H\x00\x12\x10\n\x06period\x18\x01 \x01(\x04H\x00\x12\x36\n\x07\x63ounter\x18\x04 \x01(\x0e\x32#.perfetto.protos.PerfEvents.CounterH\x01\x12<\n\ntracepoint\x18\x03 \x01(\x0b\x32&.perfetto.protos.PerfEvents.TracepointH\x01\x12\x39\n\traw_event\x18\x05 \x01(\x0b\x32$.perfetto.protos.PerfEvents.RawEventH\x01\x12>\n\x0ftimestamp_clock\x18\x0b \x01(\x0e\x32%.perfetto.protos.PerfEvents.PerfClock\x12\x0c\n\x04name\x18\n \x01(\tB\n\n\x08intervalB\x07\n\x05\x65vent\x1a*\n\nTracepoint\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x0e\n\x06\x66ilter\x18\x02 \x01(\t\x1aJ\n\x08RawEvent\x12\x0c\n\x04type\x18\x01 \x01(\r\x12\x0e\n\x06\x63onfig\x18\x02 \x01(\x04\x12\x0f\n\x07\x63onfig1\x18\x03 \x01(\x04\x12\x0f\n\x07\x63onfig2\x18\x04 \x01(\x04"\xe8\x03\n\x07\x43ounter\x12\x13\n\x0fUNKNOWN_COUNTER\x10\x00\x12\x10\n\x0cSW_CPU_CLOCK\x10\x01\x12\x12\n\x0eSW_PAGE_FAULTS\x10\x02\x12\x11\n\rSW_TASK_CLOCK\x10\x03\x12\x17\n\x13SW_CONTEXT_SWITCHES\x10\x04\x12\x15\n\x11SW_CPU_MIGRATIONS\x10\x05\x12\x16\n\x12SW_PAGE_FAULTS_MIN\x10\x06\x12\x16\n\x12SW_PAGE_FAULTS_MAJ\x10\x07\x12\x17\n\x13SW_ALIGNMENT_FAULTS\x10\x08\x12\x17\n\x13SW_EMULATION_FAULTS\x10\t\x12\x0c\n\x08SW_DUMMY\x10\x14\x12\x11\n\rHW_CPU_CYCLES\x10\n\x12\x13\n\x0fHW_INSTRUCTIONS\x10\x0b\x12\x17\n\x13HW_CACHE_REFERENCES\x10\x0c\x12\x13\n\x0fHW_CACHE_MISSES\x10\r\x12\x1a\n\x16HW_BRANCH_INSTRUCTIONS\x10\x0e\x12\x14\n\x10HW_BRANCH_MISSES\x10\x0f\x12\x11\n\rHW_BUS_CYCLES\x10\x10\x12\x1e\n\x1aHW_STALLED_CYCLES_FRONTEND\x10\x11\x12\x1d\n\x19HW_STALLED_CYCLES_BACKEND\x10\x12\x12\x15\n\x11HW_REF_CPU_CYCLES\x10\x13"\x8d\x01\n\tPerfClock\x12\x16\n\x12UNKNOWN_PERF_CLOCK\x10\x00\x12\x17\n\x13PERF_CLOCK_REALTIME\x10\x01\x12\x18\n\x14PERF_CLOCK_MONOTONIC\x10\x02\x12\x1c\n\x18PERF_CLOCK_MONOTONIC_RAW\x10\x03\x12\x17\n\x13PERF_CLOCK_BOOTTIME\x10\x04"\xd7\x07\n\x0fPerfEventConfig\x12\x36\n\x08timebase\x18\x0f \x01(\x0b\x32$.perfetto.protos.PerfEvents.Timebase\x12N\n\x12\x63\x61llstack_sampling\x18\x10 \x01(\x0b\x32\x32.perfetto.protos.PerfEventConfig.CallstackSampling\x12"\n\x1aring_buffer_read_period_ms\x18\x08 \x01(\r\x12\x19\n\x11ring_buffer_pages\x18\x03 \x01(\r\x12!\n\x19max_enqueued_footprint_kb\x18\x11 \x01(\x04\x12\x1c\n\x14max_daemon_memory_kb\x18\r \x01(\r\x12$\n\x1cremote_descriptor_timeout_ms\x18\t \x01(\r\x12$\n\x1cunwind_state_clear_period_ms\x18\n \x01(\r\x12\x1b\n\x13target_installed_by\x18\x12 \x03(\t\x12\x10\n\x08\x61ll_cpus\x18\x01 \x01(\x08\x12\x1a\n\x12sampling_frequency\x18\x02 \x01(\r\x12\x15\n\rkernel_frames\x18\x0c \x01(\x08\x12\x12\n\ntarget_pid\x18\x04 \x03(\x05\x12\x16\n\x0etarget_cmdline\x18\x05 \x03(\t\x12\x13\n\x0b\x65xclude_pid\x18\x06 \x03(\x05\x12\x17\n\x0f\x65xclude_cmdline\x18\x07 \x03(\t\x12 \n\x18\x61\x64\x64itional_cmdline_count\x18\x0b \x01(\r\x1a\xa3\x01\n\x11\x43\x61llstackSampling\x12\x35\n\x05scope\x18\x01 \x01(\x0b\x32&.perfetto.protos.PerfEventConfig.Scope\x12\x15\n\rkernel_frames\x18\x02 \x01(\x08\x12@\n\x0buser_frames\x18\x03 \x01(\x0e\x32+.perfetto.protos.PerfEventConfig.UnwindMode\x1a\xa0\x01\n\x05Scope\x12\x12\n\ntarget_pid\x18\x01 \x03(\x05\x12\x16\n\x0etarget_cmdline\x18\x02 \x03(\t\x12\x13\n\x0b\x65xclude_pid\x18\x03 \x03(\x05\x12\x17\n\x0f\x65xclude_cmdline\x18\x04 \x03(\t\x12 \n\x18\x61\x64\x64itional_cmdline_count\x18\x05 \x01(\r\x12\x1b\n\x13process_shard_count\x18\x06 \x01(\r"C\n\nUnwindMode\x12\x12\n\x0eUNWIND_UNKNOWN\x10\x00\x12\x0f\n\x0bUNWIND_SKIP\x10\x01\x12\x10\n\x0cUNWIND_DWARF\x10\x02J\x04\x08\x0e\x10\x0f"\x9a\x01\n\x13StatsdTracingConfig\x12-\n\x0cpush_atom_id\x18\x01 \x03(\x0e\x32\x17.perfetto.protos.AtomId\x12\x18\n\x10raw_push_atom_id\x18\x02 \x03(\x05\x12:\n\x0bpull_config\x18\x03 \x03(\x0b\x32%.perfetto.protos.StatsdPullAtomConfig"\x8c\x01\n\x14StatsdPullAtomConfig\x12-\n\x0cpull_atom_id\x18\x01 \x03(\x0e\x32\x17.perfetto.protos.AtomId\x12\x18\n\x10raw_pull_atom_id\x18\x02 \x03(\x05\x12\x19\n\x11pull_frequency_ms\x18\x03 \x01(\x05\x12\x10\n\x08packages\x18\x04 \x03(\t"\xec\x04\n\x0eSysStatsConfig\x12\x19\n\x11meminfo_period_ms\x18\x01 \x01(\r\x12:\n\x10meminfo_counters\x18\x02 \x03(\x0e\x32 .perfetto.protos.MeminfoCounters\x12\x18\n\x10vmstat_period_ms\x18\x03 \x01(\r\x12\x38\n\x0fvmstat_counters\x18\x04 \x03(\x0e\x32\x1f.perfetto.protos.VmstatCounters\x12\x16\n\x0estat_period_ms\x18\x05 \x01(\r\x12\x43\n\rstat_counters\x18\x06 \x03(\x0e\x32,.perfetto.protos.SysStatsConfig.StatCounters\x12\x19\n\x11\x64\x65vfreq_period_ms\x18\x07 \x01(\r\x12\x19\n\x11\x63pufreq_period_ms\x18\x08 \x01(\r\x12\x1b\n\x13\x62uddyinfo_period_ms\x18\t \x01(\r\x12\x1a\n\x12\x64iskstat_period_ms\x18\n \x01(\r\x12\x15\n\rpsi_period_ms\x18\x0b \x01(\r\x12\x19\n\x11thermal_period_ms\x18\x0c \x01(\r\x12\x19\n\x11\x63puidle_period_ms\x18\r \x01(\r\x12\x19\n\x11gpufreq_period_ms\x18\x0e \x01(\r"{\n\x0cStatCounters\x12\x14\n\x10STAT_UNSPECIFIED\x10\x00\x12\x12\n\x0eSTAT_CPU_TIMES\x10\x01\x12\x13\n\x0fSTAT_IRQ_COUNTS\x10\x02\x12\x17\n\x13STAT_SOFTIRQ_COUNTS\x10\x03\x12\x13\n\x0fSTAT_FORK_COUNT\x10\x04"\x12\n\x10SystemInfoConfig"\x8d\x04\n\nTestConfig\x12\x15\n\rmessage_count\x18\x01 \x01(\r\x12\x1f\n\x17max_messages_per_second\x18\x02 \x01(\r\x12\x0c\n\x04seed\x18\x03 \x01(\r\x12\x14\n\x0cmessage_size\x18\x04 \x01(\r\x12\x1e\n\x16send_batch_on_register\x18\x05 \x01(\x08\x12=\n\x0c\x64ummy_fields\x18\x06 \x01(\x0b\x32\'.perfetto.protos.TestConfig.DummyFields\x1a\xc3\x02\n\x0b\x44ummyFields\x12\x14\n\x0c\x66ield_uint32\x18\x01 \x01(\r\x12\x13\n\x0b\x66ield_int32\x18\x02 \x01(\x05\x12\x14\n\x0c\x66ield_uint64\x18\x03 \x01(\x04\x12\x13\n\x0b\x66ield_int64\x18\x04 \x01(\x03\x12\x15\n\rfield_fixed64\x18\x05 \x01(\x06\x12\x16\n\x0e\x66ield_sfixed64\x18\x06 \x01(\x10\x12\x15\n\rfield_fixed32\x18\x07 \x01(\x07\x12\x16\n\x0e\x66ield_sfixed32\x18\x08 \x01(\x0f\x12\x14\n\x0c\x66ield_double\x18\t \x01(\x01\x12\x13\n\x0b\x66ield_float\x18\n \x01(\x02\x12\x14\n\x0c\x66ield_sint64\x18\x0b \x01(\x12\x12\x14\n\x0c\x66ield_sint32\x18\x0c \x01(\x11\x12\x14\n\x0c\x66ield_string\x18\r \x01(\t\x12\x13\n\x0b\x66ield_bytes\x18\x0e \x01(\x0c"\xae\x02\n\x10TrackEventConfig\x12\x1b\n\x13\x64isabled_categories\x18\x01 \x03(\t\x12\x1a\n\x12\x65nabled_categories\x18\x02 \x03(\t\x12\x15\n\rdisabled_tags\x18\x03 \x03(\t\x12\x14\n\x0c\x65nabled_tags\x18\x04 \x03(\t\x12&\n\x1e\x64isable_incremental_timestamps\x18\x05 \x01(\x08\x12!\n\x19timestamp_unit_multiplier\x18\x06 \x01(\x04\x12 \n\x18\x66ilter_debug_annotations\x18\x07 \x01(\x08\x12#\n\x1b\x65nable_thread_time_sampling\x18\x08 \x01(\x08\x12"\n\x1a\x66ilter_dynamic_event_names\x18\t \x01(\x08"\xba\x14\n\x10\x44\x61taSourceConfig\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x15\n\rtarget_buffer\x18\x02 \x01(\r\x12\x19\n\x11trace_duration_ms\x18\x03 \x01(\r\x12)\n!prefer_suspend_clock_for_duration\x18z \x01(\x08\x12\x17\n\x0fstop_timeout_ms\x18\x07 \x01(\r\x12\x1f\n\x17\x65nable_extra_guardrails\x18\x06 \x01(\x08\x12M\n\x11session_initiator\x18\x08 \x01(\x0e\x32\x32.perfetto.protos.DataSourceConfig.SessionInitiator\x12\x1a\n\x12tracing_session_id\x18\x04 \x01(\x04\x12\x38\n\rftrace_config\x18\x64 \x01(\x0b\x32\x1d.perfetto.protos.FtraceConfigB\x02(\x01\x12?\n\x11inode_file_config\x18\x66 \x01(\x0b\x32 .perfetto.protos.InodeFileConfigB\x02(\x01\x12\x45\n\x14process_stats_config\x18g \x01(\x0b\x32#.perfetto.protos.ProcessStatsConfigB\x02(\x01\x12=\n\x10sys_stats_config\x18h \x01(\x0b\x32\x1f.perfetto.protos.SysStatsConfigB\x02(\x01\x12>\n\x10heapprofd_config\x18i \x01(\x0b\x32 .perfetto.protos.HeapprofdConfigB\x02(\x01\x12?\n\x11java_hprof_config\x18n \x01(\x0b\x32 .perfetto.protos.JavaHprofConfigB\x02(\x01\x12\x45\n\x14\x61ndroid_power_config\x18j \x01(\x0b\x32#.perfetto.protos.AndroidPowerConfigB\x02(\x01\x12\x41\n\x12\x61ndroid_log_config\x18k \x01(\x0b\x32!.perfetto.protos.AndroidLogConfigB\x02(\x01\x12\x41\n\x12gpu_counter_config\x18l \x01(\x0b\x32!.perfetto.protos.GpuCounterConfigB\x02(\x01\x12\x65\n%android_game_intervention_list_config\x18t \x01(\x0b\x32\x32.perfetto.protos.AndroidGameInterventionListConfigB\x02(\x01\x12\x45\n\x14packages_list_config\x18m \x01(\x0b\x32#.perfetto.protos.PackagesListConfigB\x02(\x01\x12?\n\x11perf_event_config\x18o \x01(\x0b\x32 .perfetto.protos.PerfEventConfigB\x02(\x01\x12\x45\n\x14vulkan_memory_config\x18p \x01(\x0b\x32#.perfetto.protos.VulkanMemoryConfigB\x02(\x01\x12\x41\n\x12track_event_config\x18q \x01(\x0b\x32!.perfetto.protos.TrackEventConfigB\x02(\x01\x12R\n\x1b\x61ndroid_polled_state_config\x18r \x01(\x0b\x32).perfetto.protos.AndroidPolledStateConfigB\x02(\x01\x12X\n\x1e\x61ndroid_system_property_config\x18v \x01(\x0b\x32,.perfetto.protos.AndroidSystemPropertyConfigB\x02(\x01\x12G\n\x15statsd_tracing_config\x18u \x01(\x0b\x32$.perfetto.protos.StatsdTracingConfigB\x02(\x01\x12=\n\x12system_info_config\x18w \x01(\x0b\x32!.perfetto.protos.SystemInfoConfig\x12\x34\n\rchrome_config\x18\x65 \x01(\x0b\x32\x1d.perfetto.protos.ChromeConfig\x12\x30\n\tv8_config\x18\x7f \x01(\x0b\x32\x19.perfetto.protos.V8ConfigB\x02(\x01\x12>\n\x12interceptor_config\x18s \x01(\x0b\x32".perfetto.protos.InterceptorConfig\x12R\n\x1bnetwork_packet_trace_config\x18x \x01(\x0b\x32).perfetto.protos.NetworkPacketTraceConfigB\x02(\x01\x12U\n\x1csurfaceflinger_layers_config\x18y \x01(\x0b\x32+.perfetto.protos.SurfaceFlingerLayersConfigB\x02(\x01\x12\x61\n"surfaceflinger_transactions_config\x18{ \x01(\x0b\x32\x31.perfetto.protos.SurfaceFlingerTransactionsConfigB\x02(\x01\x12[\n android_sdk_sysprop_guard_config\x18| \x01(\x0b\x32-.perfetto.protos.AndroidSdkSyspropGuardConfigB\x02(\x01\x12\x32\n\netw_config\x18} \x01(\x0b\x32\x1a.perfetto.protos.EtwConfigB\x02(\x01\x12<\n\x0fprotolog_config\x18~ \x01(\x0b\x32\x1f.perfetto.protos.ProtoLogConfigB\x02(\x01\x12Q\n\x1a\x61ndroid_input_event_config\x18\x80\x01 \x01(\x0b\x32(.perfetto.protos.AndroidInputEventConfigB\x02(\x01\x12\x42\n\x12pixel_modem_config\x18\x81\x01 \x01(\x0b\x32!.perfetto.protos.PixelModemConfigB\x02(\x01\x12G\n\x14windowmanager_config\x18\x82\x01 \x01(\x0b\x32$.perfetto.protos.WindowManagerConfigB\x02(\x01\x12\x16\n\rlegacy_config\x18\xe8\x07 \x01(\t\x12\x31\n\x0b\x66or_testing\x18\xe9\x07 \x01(\x0b\x32\x1b.perfetto.protos.TestConfig"[\n\x10SessionInitiator\x12!\n\x1dSESSION_INITIATOR_UNSPECIFIED\x10\x00\x12$\n SESSION_INITIATOR_TRUSTED_SYSTEM\x10\x01J\x0b\x08\xff\xff\xff\x7f\x10\x80\x80\x80\x80\x01"\xe9#\n\x0bTraceConfig\x12:\n\x07\x62uffers\x18\x01 \x03(\x0b\x32).perfetto.protos.TraceConfig.BufferConfig\x12=\n\x0c\x64\x61ta_sources\x18\x02 \x03(\x0b\x32\'.perfetto.protos.TraceConfig.DataSource\x12L\n\x14\x62uiltin_data_sources\x18\x14 \x01(\x0b\x32..perfetto.protos.TraceConfig.BuiltinDataSource\x12\x13\n\x0b\x64uration_ms\x18\x03 \x01(\r\x12)\n!prefer_suspend_clock_for_duration\x18$ \x01(\x08\x12\x1f\n\x17\x65nable_extra_guardrails\x18\x04 \x01(\x08\x12I\n\rlockdown_mode\x18\x05 \x01(\x0e\x32\x32.perfetto.protos.TraceConfig.LockdownModeOperation\x12>\n\tproducers\x18\x06 \x03(\x0b\x32+.perfetto.protos.TraceConfig.ProducerConfig\x12\x44\n\x0fstatsd_metadata\x18\x07 \x01(\x0b\x32+.perfetto.protos.TraceConfig.StatsdMetadata\x12\x17\n\x0fwrite_into_file\x18\x08 \x01(\x08\x12\x13\n\x0boutput_path\x18\x1d \x01(\t\x12\x1c\n\x14\x66ile_write_period_ms\x18\t \x01(\r\x12\x1b\n\x13max_file_size_bytes\x18\n \x01(\x04\x12L\n\x13guardrail_overrides\x18\x0b \x01(\x0b\x32/.perfetto.protos.TraceConfig.GuardrailOverrides\x12\x16\n\x0e\x64\x65\x66\x65rred_start\x18\x0c \x01(\x08\x12\x17\n\x0f\x66lush_period_ms\x18\r \x01(\r\x12\x18\n\x10\x66lush_timeout_ms\x18\x0e \x01(\r\x12#\n\x1b\x64\x61ta_source_stop_timeout_ms\x18\x17 \x01(\r\x12\x16\n\x0enotify_traceur\x18\x10 \x01(\x08\x12\x17\n\x0f\x62ugreport_score\x18\x1e \x01(\x05\x12\x1a\n\x12\x62ugreport_filename\x18& \x01(\t\x12\x42\n\x0etrigger_config\x18\x11 \x01(\x0b\x32*.perfetto.protos.TraceConfig.TriggerConfig\x12\x19\n\x11\x61\x63tivate_triggers\x18\x12 \x03(\t\x12U\n\x18incremental_state_config\x18\x15 \x01(\x0b\x32\x33.perfetto.protos.TraceConfig.IncrementalStateConfig\x12 \n\x18\x61llow_user_build_tracing\x18\x13 \x01(\x08\x12\x1b\n\x13unique_session_name\x18\x16 \x01(\t\x12\x46\n\x10\x63ompression_type\x18\x18 \x01(\x0e\x32,.perfetto.protos.TraceConfig.CompressionType\x12Q\n\x16incident_report_config\x18\x19 \x01(\x0b\x32\x31.perfetto.protos.TraceConfig.IncidentReportConfig\x12\x42\n\x0estatsd_logging\x18\x1f \x01(\x0e\x32*.perfetto.protos.TraceConfig.StatsdLogging\x12\x1a\n\x0etrace_uuid_msb\x18\x1b \x01(\x03\x42\x02\x18\x01\x12\x1a\n\x0etrace_uuid_lsb\x18\x1c \x01(\x03\x42\x02\x18\x01\x12>\n\x0ctrace_filter\x18! \x01(\x0b\x32(.perfetto.protos.TraceConfig.TraceFilter\x12O\n\x15\x61ndroid_report_config\x18" \x01(\x0b\x32\x30.perfetto.protos.TraceConfig.AndroidReportConfig\x12N\n\x15\x63md_trace_start_delay\x18# \x01(\x0b\x32/.perfetto.protos.TraceConfig.CmdTraceStartDelay\x12I\n\x12session_semaphores\x18\' \x03(\x0b\x32-.perfetto.protos.TraceConfig.SessionSemaphore\x1a\xea\x01\n\x0c\x42ufferConfig\x12\x0f\n\x07size_kb\x18\x01 \x01(\r\x12I\n\x0b\x66ill_policy\x18\x04 \x01(\x0e\x32\x34.perfetto.protos.TraceConfig.BufferConfig.FillPolicy\x12\x19\n\x11transfer_on_clone\x18\x05 \x01(\x08\x12\x1a\n\x12\x63lear_before_clone\x18\x06 \x01(\x08";\n\nFillPolicy\x12\x0f\n\x0bUNSPECIFIED\x10\x00\x12\x0f\n\x0bRING_BUFFER\x10\x01\x12\x0b\n\x07\x44ISCARD\x10\x02J\x04\x08\x02\x10\x03J\x04\x08\x03\x10\x04\x1a\x81\x01\n\nDataSource\x12\x31\n\x06\x63onfig\x18\x01 \x01(\x0b\x32!.perfetto.protos.DataSourceConfig\x12\x1c\n\x14producer_name_filter\x18\x02 \x03(\t\x12"\n\x1aproducer_name_regex_filter\x18\x03 \x03(\t\x1a\xbf\x02\n\x11\x42uiltinDataSource\x12"\n\x1a\x64isable_clock_snapshotting\x18\x01 \x01(\x08\x12\x1c\n\x14\x64isable_trace_config\x18\x02 \x01(\x08\x12\x1b\n\x13\x64isable_system_info\x18\x03 \x01(\x08\x12\x1e\n\x16\x64isable_service_events\x18\x04 \x01(\x08\x12:\n\x13primary_trace_clock\x18\x05 \x01(\x0e\x32\x1d.perfetto.protos.BuiltinClock\x12\x1c\n\x14snapshot_interval_ms\x18\x06 \x01(\r\x12)\n!prefer_suspend_clock_for_snapshot\x18\x07 \x01(\x08\x12&\n\x1e\x64isable_chunk_usage_histograms\x18\x08 \x01(\x08\x1aR\n\x0eProducerConfig\x12\x15\n\rproducer_name\x18\x01 \x01(\t\x12\x13\n\x0bshm_size_kb\x18\x02 \x01(\r\x12\x14\n\x0cpage_size_kb\x18\x03 \x01(\r\x1a\x8e\x01\n\x0eStatsdMetadata\x12\x1b\n\x13triggering_alert_id\x18\x01 \x01(\x03\x12\x1d\n\x15triggering_config_uid\x18\x02 \x01(\x05\x12\x1c\n\x14triggering_config_id\x18\x03 \x01(\x03\x12"\n\x1atriggering_subscription_id\x18\x04 \x01(\x03\x1a^\n\x12GuardrailOverrides\x12$\n\x18max_upload_per_day_bytes\x18\x01 \x01(\x04\x42\x02\x18\x01\x12"\n\x1amax_tracing_buffer_size_kb\x18\x02 \x01(\r\x1a\xca\x03\n\rTriggerConfig\x12L\n\x0ctrigger_mode\x18\x01 \x01(\x0e\x32\x36.perfetto.protos.TraceConfig.TriggerConfig.TriggerMode\x12\'\n\x1fuse_clone_snapshot_if_available\x18\x05 \x01(\x08\x12\x44\n\x08triggers\x18\x02 \x03(\x0b\x32\x32.perfetto.protos.TraceConfig.TriggerConfig.Trigger\x12\x1a\n\x12trigger_timeout_ms\x18\x03 \x01(\r\x1a{\n\x07Trigger\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x1b\n\x13producer_name_regex\x18\x02 \x01(\t\x12\x15\n\rstop_delay_ms\x18\x03 \x01(\r\x12\x14\n\x0cmax_per_24_h\x18\x04 \x01(\r\x12\x18\n\x10skip_probability\x18\x05 \x01(\x01"]\n\x0bTriggerMode\x12\x0f\n\x0bUNSPECIFIED\x10\x00\x12\x11\n\rSTART_TRACING\x10\x01\x12\x10\n\x0cSTOP_TRACING\x10\x02\x12\x12\n\x0e\x43LONE_SNAPSHOT\x10\x04"\x04\x08\x03\x10\x03J\x04\x08\x04\x10\x05\x1a\x31\n\x16IncrementalStateConfig\x12\x17\n\x0f\x63lear_period_ms\x18\x01 \x01(\r\x1a\x97\x01\n\x14IncidentReportConfig\x12\x1b\n\x13\x64\x65stination_package\x18\x01 \x01(\t\x12\x19\n\x11\x64\x65stination_class\x18\x02 \x01(\t\x12\x15\n\rprivacy_level\x18\x03 \x01(\x05\x12\x16\n\x0eskip_incidentd\x18\x05 \x01(\x08\x12\x18\n\x0cskip_dropbox\x18\x04 \x01(\x08\x42\x02\x18\x01\x1a\xd5\x04\n\x0bTraceFilter\x12\x10\n\x08\x62ytecode\x18\x01 \x01(\x0c\x12\x13\n\x0b\x62ytecode_v2\x18\x02 \x01(\x0c\x12W\n\x13string_filter_chain\x18\x03 \x01(\x0b\x32:.perfetto.protos.TraceConfig.TraceFilter.StringFilterChain\x1a\x9a\x01\n\x10StringFilterRule\x12K\n\x06policy\x18\x01 \x01(\x0e\x32;.perfetto.protos.TraceConfig.TraceFilter.StringFilterPolicy\x12\x15\n\rregex_pattern\x18\x02 \x01(\t\x12"\n\x1a\x61trace_payload_starts_with\x18\x03 \x01(\t\x1a]\n\x11StringFilterChain\x12H\n\x05rules\x18\x01 \x03(\x0b\x32\x39.perfetto.protos.TraceConfig.TraceFilter.StringFilterRule"\xc9\x01\n\x12StringFilterPolicy\x12\x13\n\x0fSFP_UNSPECIFIED\x10\x00\x12\x1b\n\x17SFP_MATCH_REDACT_GROUPS\x10\x01\x12"\n\x1eSFP_ATRACE_MATCH_REDACT_GROUPS\x10\x02\x12\x13\n\x0fSFP_MATCH_BREAK\x10\x03\x12\x1a\n\x16SFP_ATRACE_MATCH_BREAK\x10\x04\x12,\n(SFP_ATRACE_REPEATED_SEARCH_REDACT_GROUPS\x10\x05\x1a\x97\x01\n\x13\x41ndroidReportConfig\x12 \n\x18reporter_service_package\x18\x01 \x01(\t\x12\x1e\n\x16reporter_service_class\x18\x02 \x01(\t\x12\x13\n\x0bskip_report\x18\x03 \x01(\x08\x12)\n!use_pipe_in_framework_for_testing\x18\x04 \x01(\x08\x1a@\n\x12\x43mdTraceStartDelay\x12\x14\n\x0cmin_delay_ms\x18\x01 \x01(\r\x12\x14\n\x0cmax_delay_ms\x18\x02 \x01(\r\x1a\x41\n\x10SessionSemaphore\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x1f\n\x17max_other_session_count\x18\x02 \x01(\x04"U\n\x15LockdownModeOperation\x12\x16\n\x12LOCKDOWN_UNCHANGED\x10\x00\x12\x12\n\x0eLOCKDOWN_CLEAR\x10\x01\x12\x10\n\x0cLOCKDOWN_SET\x10\x02"Q\n\x0f\x43ompressionType\x12 \n\x1c\x43OMPRESSION_TYPE_UNSPECIFIED\x10\x00\x12\x1c\n\x18\x43OMPRESSION_TYPE_DEFLATE\x10\x01"h\n\rStatsdLogging\x12\x1e\n\x1aSTATSD_LOGGING_UNSPECIFIED\x10\x00\x12\x1a\n\x16STATSD_LOGGING_ENABLED\x10\x01\x12\x1b\n\x17STATSD_LOGGING_DISABLED\x10\x02J\x04\x08\x0f\x10\x10J\x04\x08%\x10&J\x04\x08\x1a\x10\x1bJ\x04\x08 \x10!"\x91\x0c\n\nTraceStats\x12=\n\x0c\x62uffer_stats\x18\x01 \x03(\x0b\x32\'.perfetto.protos.TraceStats.BufferStats\x12#\n\x1b\x63hunk_payload_histogram_def\x18\x11 \x03(\x03\x12=\n\x0cwriter_stats\x18\x12 \x03(\x0b\x32\'.perfetto.protos.TraceStats.WriterStats\x12\x1b\n\x13producers_connected\x18\x02 \x01(\r\x12\x16\n\x0eproducers_seen\x18\x03 \x01(\x04\x12\x1f\n\x17\x64\x61ta_sources_registered\x18\x04 \x01(\r\x12\x19\n\x11\x64\x61ta_sources_seen\x18\x05 \x01(\x04\x12\x18\n\x10tracing_sessions\x18\x06 \x01(\r\x12\x15\n\rtotal_buffers\x18\x07 \x01(\r\x12\x18\n\x10\x63hunks_discarded\x18\x08 \x01(\x04\x12\x19\n\x11patches_discarded\x18\t \x01(\x04\x12\x17\n\x0finvalid_packets\x18\n \x01(\x04\x12=\n\x0c\x66ilter_stats\x18\x0b \x01(\x0b\x32\'.perfetto.protos.TraceStats.FilterStats\x12\x19\n\x11\x66lushes_requested\x18\x0c \x01(\x04\x12\x19\n\x11\x66lushes_succeeded\x18\r \x01(\x04\x12\x16\n\x0e\x66lushes_failed\x18\x0e \x01(\x04\x12J\n\x13\x66inal_flush_outcome\x18\x0f \x01(\x0e\x32-.perfetto.protos.TraceStats.FinalFlushOutcome\x1a\x8a\x04\n\x0b\x42ufferStats\x12\x13\n\x0b\x62uffer_size\x18\x0c \x01(\x04\x12\x15\n\rbytes_written\x18\x01 \x01(\x04\x12\x19\n\x11\x62ytes_overwritten\x18\r \x01(\x04\x12\x12\n\nbytes_read\x18\x0e \x01(\x04\x12\x1d\n\x15padding_bytes_written\x18\x0f \x01(\x04\x12\x1d\n\x15padding_bytes_cleared\x18\x10 \x01(\x04\x12\x16\n\x0e\x63hunks_written\x18\x02 \x01(\x04\x12\x18\n\x10\x63hunks_rewritten\x18\n \x01(\x04\x12\x1a\n\x12\x63hunks_overwritten\x18\x03 \x01(\x04\x12\x18\n\x10\x63hunks_discarded\x18\x12 \x01(\x04\x12\x13\n\x0b\x63hunks_read\x18\x11 \x01(\x04\x12%\n\x1d\x63hunks_committed_out_of_order\x18\x0b \x01(\x04\x12\x18\n\x10write_wrap_count\x18\x04 \x01(\x04\x12\x19\n\x11patches_succeeded\x18\x05 \x01(\x04\x12\x16\n\x0epatches_failed\x18\x06 \x01(\x04\x12\x1c\n\x14readaheads_succeeded\x18\x07 \x01(\x04\x12\x19\n\x11readaheads_failed\x18\x08 \x01(\x04\x12\x16\n\x0e\x61\x62i_violations\x18\t \x01(\x04\x12 \n\x18trace_writer_packet_loss\x18\x13 \x01(\x04\x1a\x87\x01\n\x0bWriterStats\x12\x13\n\x0bsequence_id\x18\x01 \x01(\x04\x12\x0e\n\x06\x62uffer\x18\x04 \x01(\r\x12*\n\x1e\x63hunk_payload_histogram_counts\x18\x02 \x03(\x04\x42\x02\x10\x01\x12\'\n\x1b\x63hunk_payload_histogram_sum\x18\x03 \x03(\x03\x42\x02\x10\x01\x1a\x9a\x01\n\x0b\x46ilterStats\x12\x15\n\rinput_packets\x18\x01 \x01(\x04\x12\x13\n\x0binput_bytes\x18\x02 \x01(\x04\x12\x14\n\x0coutput_bytes\x18\x03 \x01(\x04\x12\x0e\n\x06\x65rrors\x18\x04 \x01(\x04\x12\x15\n\rtime_taken_ns\x18\x05 \x01(\x04\x12"\n\x1a\x62ytes_discarded_per_buffer\x18\x14 \x03(\x04"c\n\x11\x46inalFlushOutcome\x12\x1b\n\x17\x46INAL_FLUSH_UNSPECIFIED\x10\x00\x12\x19\n\x15\x46INAL_FLUSH_SUCCEEDED\x10\x01\x12\x16\n\x12\x46INAL_FLUSH_FAILED\x10\x02"\x8f\x03\n\x1b\x41ndroidGameInterventionList\x12S\n\rgame_packages\x18\x01 \x03(\x0b\x32<.perfetto.protos.AndroidGameInterventionList.GamePackageInfo\x12\x13\n\x0bparse_error\x18\x02 \x01(\x08\x12\x12\n\nread_error\x18\x03 \x01(\x08\x1aZ\n\x0cGameModeInfo\x12\x0c\n\x04mode\x18\x01 \x01(\r\x12\x11\n\tuse_angle\x18\x02 \x01(\x08\x12\x1c\n\x14resolution_downscale\x18\x03 \x01(\x02\x12\x0b\n\x03\x66ps\x18\x04 \x01(\x02\x1a\x95\x01\n\x0fGamePackageInfo\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x0b\n\x03uid\x18\x02 \x01(\x04\x12\x14\n\x0c\x63urrent_mode\x18\x03 \x01(\r\x12Q\n\x0egame_mode_info\x18\x04 \x03(\x0b\x32\x39.perfetto.protos.AndroidGameInterventionList.GameModeInfo"\xb2\x04\n\x10\x41ndroidLogPacket\x12:\n\x06\x65vents\x18\x01 \x03(\x0b\x32*.perfetto.protos.AndroidLogPacket.LogEvent\x12\x36\n\x05stats\x18\x02 \x01(\x0b\x32\'.perfetto.protos.AndroidLogPacket.Stats\x1a\xe4\x02\n\x08LogEvent\x12-\n\x06log_id\x18\x01 \x01(\x0e\x32\x1d.perfetto.protos.AndroidLogId\x12\x0b\n\x03pid\x18\x02 \x01(\x05\x12\x0b\n\x03tid\x18\x03 \x01(\x05\x12\x0b\n\x03uid\x18\x04 \x01(\x05\x12\x11\n\ttimestamp\x18\x05 \x01(\x04\x12\x0b\n\x03tag\x18\x06 \x01(\t\x12\x31\n\x04prio\x18\x07 \x01(\x0e\x32#.perfetto.protos.AndroidLogPriority\x12\x0f\n\x07message\x18\x08 \x01(\t\x12<\n\x04\x61rgs\x18\t \x03(\x0b\x32..perfetto.protos.AndroidLogPacket.LogEvent.Arg\x1a`\n\x03\x41rg\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x13\n\tint_value\x18\x02 \x01(\x03H\x00\x12\x15\n\x0b\x66loat_value\x18\x03 \x01(\x02H\x00\x12\x16\n\x0cstring_value\x18\x04 \x01(\tH\x00\x42\x07\n\x05value\x1a\x43\n\x05Stats\x12\x11\n\tnum_total\x18\x01 \x01(\x04\x12\x12\n\nnum_failed\x18\x02 \x01(\x04\x12\x13\n\x0bnum_skipped\x18\x03 \x01(\x04"\x8b\x01\n\x15\x41ndroidSystemProperty\x12\x44\n\x06values\x18\x01 \x03(\x0b\x32\x34.perfetto.protos.AndroidSystemProperty.PropertyValue\x1a,\n\rPropertyValue\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t"\x82\x07\n\x17\x41ndroidCameraFrameEvent\x12\x12\n\nsession_id\x18\x01 \x01(\x04\x12\x11\n\tcamera_id\x18\x02 \x01(\r\x12\x14\n\x0c\x66rame_number\x18\x03 \x01(\x03\x12\x12\n\nrequest_id\x18\x04 \x01(\x03\x12\x1b\n\x13request_received_ns\x18\x05 \x01(\x03\x12%\n\x1drequest_processing_started_ns\x18\x06 \x01(\x03\x12\x1c\n\x14start_of_exposure_ns\x18\x07 \x01(\x03\x12\x19\n\x11start_of_frame_ns\x18\x08 \x01(\x03\x12\x1d\n\x15responses_all_sent_ns\x18\t \x01(\x03\x12[\n\x15\x63\x61pture_result_status\x18\n \x01(\x0e\x32<.perfetto.protos.AndroidCameraFrameEvent.CaptureResultStatus\x12\x1d\n\x15skipped_sensor_frames\x18\x0b \x01(\x05\x12\x16\n\x0e\x63\x61pture_intent\x18\x0c \x01(\x05\x12\x13\n\x0bnum_streams\x18\r \x01(\x05\x12\x65\n\x17node_processing_details\x18\x0e \x03(\x0b\x32\x44.perfetto.protos.AndroidCameraFrameEvent.CameraNodeProcessingDetails\x12\x1b\n\x13vendor_data_version\x18\x0f \x01(\x05\x12\x13\n\x0bvendor_data\x18\x10 \x01(\x0c\x1a\x85\x01\n\x1b\x43\x61meraNodeProcessingDetails\x12\x0f\n\x07node_id\x18\x01 \x01(\x03\x12\x1b\n\x13start_processing_ns\x18\x02 \x01(\x03\x12\x19\n\x11\x65nd_processing_ns\x18\x03 \x01(\x03\x12\x1d\n\x15scheduling_latency_ns\x18\x04 \x01(\x03"\xaf\x01\n\x13\x43\x61ptureResultStatus\x12\x16\n\x12STATUS_UNSPECIFIED\x10\x00\x12\r\n\tSTATUS_OK\x10\x01\x12\x1f\n\x1bSTATUS_EARLY_METADATA_ERROR\x10\x02\x12\x1f\n\x1bSTATUS_FINAL_METADATA_ERROR\x10\x03\x12\x17\n\x13STATUS_BUFFER_ERROR\x10\x04\x12\x16\n\x12STATUS_FLUSH_ERROR\x10\x05"\xb7\x04\n\x19\x41ndroidCameraSessionStats\x12\x12\n\nsession_id\x18\x01 \x01(\x04\x12\x45\n\x05graph\x18\x02 \x01(\x0b\x32\x36.perfetto.protos.AndroidCameraSessionStats.CameraGraph\x1a\xbe\x03\n\x0b\x43\x61meraGraph\x12P\n\x05nodes\x18\x01 \x03(\x0b\x32\x41.perfetto.protos.AndroidCameraSessionStats.CameraGraph.CameraNode\x12P\n\x05\x65\x64ges\x18\x02 \x03(\x0b\x32\x41.perfetto.protos.AndroidCameraSessionStats.CameraGraph.CameraEdge\x1av\n\nCameraNode\x12\x0f\n\x07node_id\x18\x01 \x01(\x03\x12\x11\n\tinput_ids\x18\x02 \x03(\x03\x12\x12\n\noutput_ids\x18\x03 \x03(\x03\x12\x1b\n\x13vendor_data_version\x18\x04 \x01(\x05\x12\x13\n\x0bvendor_data\x18\x05 \x01(\x0c\x1a\x92\x01\n\nCameraEdge\x12\x16\n\x0eoutput_node_id\x18\x01 \x01(\x03\x12\x11\n\toutput_id\x18\x02 \x01(\x03\x12\x15\n\rinput_node_id\x18\x03 \x01(\x03\x12\x10\n\x08input_id\x18\x04 \x01(\x03\x12\x1b\n\x13vendor_data_version\x18\x05 \x01(\x05\x12\x13\n\x0bvendor_data\x18\x06 \x01(\x0c"\x95\x11\n\x12\x46rameTimelineEvent\x12\x65\n\x1c\x65xpected_display_frame_start\x18\x01 \x01(\x0b\x32=.perfetto.protos.FrameTimelineEvent.ExpectedDisplayFrameStartH\x00\x12\x61\n\x1a\x61\x63tual_display_frame_start\x18\x02 \x01(\x0b\x32;.perfetto.protos.FrameTimelineEvent.ActualDisplayFrameStartH\x00\x12\x65\n\x1c\x65xpected_surface_frame_start\x18\x03 \x01(\x0b\x32=.perfetto.protos.FrameTimelineEvent.ExpectedSurfaceFrameStartH\x00\x12\x61\n\x1a\x61\x63tual_surface_frame_start\x18\x04 \x01(\x0b\x32;.perfetto.protos.FrameTimelineEvent.ActualSurfaceFrameStartH\x00\x12\x41\n\tframe_end\x18\x05 \x01(\x0b\x32,.perfetto.protos.FrameTimelineEvent.FrameEndH\x00\x1ax\n\x19\x45xpectedSurfaceFrameStart\x12\x0e\n\x06\x63ookie\x18\x01 \x01(\x03\x12\r\n\x05token\x18\x02 \x01(\x03\x12\x1b\n\x13\x64isplay_frame_token\x18\x03 \x01(\x03\x12\x0b\n\x03pid\x18\x04 \x01(\x05\x12\x12\n\nlayer_name\x18\x05 \x01(\t\x1a\xb3\x03\n\x17\x41\x63tualSurfaceFrameStart\x12\x0e\n\x06\x63ookie\x18\x01 \x01(\x03\x12\r\n\x05token\x18\x02 \x01(\x03\x12\x1b\n\x13\x64isplay_frame_token\x18\x03 \x01(\x03\x12\x0b\n\x03pid\x18\x04 \x01(\x05\x12\x12\n\nlayer_name\x18\x05 \x01(\t\x12\x45\n\x0cpresent_type\x18\x06 \x01(\x0e\x32/.perfetto.protos.FrameTimelineEvent.PresentType\x12\x16\n\x0eon_time_finish\x18\x07 \x01(\x08\x12\x17\n\x0fgpu_composition\x18\x08 \x01(\x08\x12\x11\n\tjank_type\x18\t \x01(\x05\x12K\n\x0fprediction_type\x18\n \x01(\x0e\x32\x32.perfetto.protos.FrameTimelineEvent.PredictionType\x12\x11\n\tis_buffer\x18\x0b \x01(\x08\x12P\n\x12jank_severity_type\x18\x0c \x01(\x0e\x32\x34.perfetto.protos.FrameTimelineEvent.JankSeverityType\x1aG\n\x19\x45xpectedDisplayFrameStart\x12\x0e\n\x06\x63ookie\x18\x01 \x01(\x03\x12\r\n\x05token\x18\x02 \x01(\x03\x12\x0b\n\x03pid\x18\x03 \x01(\x05\x1a\xef\x02\n\x17\x41\x63tualDisplayFrameStart\x12\x0e\n\x06\x63ookie\x18\x01 \x01(\x03\x12\r\n\x05token\x18\x02 \x01(\x03\x12\x0b\n\x03pid\x18\x03 \x01(\x05\x12\x45\n\x0cpresent_type\x18\x04 \x01(\x0e\x32/.perfetto.protos.FrameTimelineEvent.PresentType\x12\x16\n\x0eon_time_finish\x18\x05 \x01(\x08\x12\x17\n\x0fgpu_composition\x18\x06 \x01(\x08\x12\x11\n\tjank_type\x18\x07 \x01(\x05\x12K\n\x0fprediction_type\x18\x08 \x01(\x0e\x32\x32.perfetto.protos.FrameTimelineEvent.PredictionType\x12P\n\x12jank_severity_type\x18\t \x01(\x0e\x32\x34.perfetto.protos.FrameTimelineEvent.JankSeverityType\x1a\x1a\n\x08\x46rameEnd\x12\x0e\n\x06\x63ookie\x18\x01 \x01(\x03"\xb0\x02\n\x08JankType\x12\x14\n\x10JANK_UNSPECIFIED\x10\x00\x12\r\n\tJANK_NONE\x10\x01\x12\x16\n\x12JANK_SF_SCHEDULING\x10\x02\x12\x19\n\x15JANK_PREDICTION_ERROR\x10\x04\x12\x14\n\x10JANK_DISPLAY_HAL\x10\x08\x12\x1f\n\x1bJANK_SF_CPU_DEADLINE_MISSED\x10\x10\x12\x1f\n\x1bJANK_SF_GPU_DEADLINE_MISSED\x10 \x12\x1c\n\x18JANK_APP_DEADLINE_MISSED\x10@\x12\x19\n\x14JANK_BUFFER_STUFFING\x10\x80\x01\x12\x11\n\x0cJANK_UNKNOWN\x10\x80\x02\x12\x15\n\x10JANK_SF_STUFFING\x10\x80\x04\x12\x11\n\x0cJANK_DROPPED\x10\x80\x08"d\n\x10JankSeverityType\x12\x14\n\x10SEVERITY_UNKNOWN\x10\x00\x12\x11\n\rSEVERITY_NONE\x10\x01\x12\x14\n\x10SEVERITY_PARTIAL\x10\x02\x12\x11\n\rSEVERITY_FULL\x10\x03"\x8a\x01\n\x0bPresentType\x12\x17\n\x13PRESENT_UNSPECIFIED\x10\x00\x12\x13\n\x0fPRESENT_ON_TIME\x10\x01\x12\x10\n\x0cPRESENT_LATE\x10\x02\x12\x11\n\rPRESENT_EARLY\x10\x03\x12\x13\n\x0fPRESENT_DROPPED\x10\x04\x12\x13\n\x0fPRESENT_UNKNOWN\x10\x05"r\n\x0ePredictionType\x12\x1a\n\x16PREDICTION_UNSPECIFIED\x10\x00\x12\x14\n\x10PREDICTION_VALID\x10\x01\x12\x16\n\x12PREDICTION_EXPIRED\x10\x02\x12\x16\n\x12PREDICTION_UNKNOWN\x10\x03\x42\x07\n\x05\x65vent"=\n\x10GpuMemTotalEvent\x12\x0e\n\x06gpu_id\x18\x01 \x01(\r\x12\x0b\n\x03pid\x18\x02 \x01(\r\x12\x0c\n\x04size\x18\x03 \x01(\x04"\xf1\x03\n\x12GraphicsFrameEvent\x12\x45\n\x0c\x62uffer_event\x18\x01 \x01(\x0b\x32/.perfetto.protos.GraphicsFrameEvent.BufferEvent\x1a\xa2\x01\n\x0b\x42ufferEvent\x12\x14\n\x0c\x66rame_number\x18\x01 \x01(\r\x12\x41\n\x04type\x18\x02 \x01(\x0e\x32\x33.perfetto.protos.GraphicsFrameEvent.BufferEventType\x12\x12\n\nlayer_name\x18\x03 \x01(\t\x12\x13\n\x0b\x64uration_ns\x18\x04 \x01(\x04\x12\x11\n\tbuffer_id\x18\x05 \x01(\r"\xee\x01\n\x0f\x42ufferEventType\x12\x0f\n\x0bUNSPECIFIED\x10\x00\x12\x0b\n\x07\x44\x45QUEUE\x10\x01\x12\t\n\x05QUEUE\x10\x02\x12\x08\n\x04POST\x10\x03\x12\x11\n\rACQUIRE_FENCE\x10\x04\x12\t\n\x05LATCH\x10\x05\x12\x1a\n\x16HWC_COMPOSITION_QUEUED\x10\x06\x12\x18\n\x14\x46\x41LLBACK_COMPOSITION\x10\x07\x12\x11\n\rPRESENT_FENCE\x10\x08\x12\x11\n\rRELEASE_FENCE\x10\t\x12\n\n\x06MODIFY\x10\n\x12\n\n\x06\x44\x45TACH\x10\x0b\x12\n\n\x06\x41TTACH\x10\x0c\x12\n\n\x06\x43\x41NCEL\x10\r"@\n\x13InitialDisplayState\x12\x15\n\rdisplay_state\x18\x01 \x01(\x05\x12\x12\n\nbrightness\x18\x02 \x01(\x01"\xfb\x01\n\x12NetworkPacketEvent\x12\x34\n\tdirection\x18\x01 \x01(\x0e\x32!.perfetto.protos.TrafficDirection\x12\x11\n\tinterface\x18\x02 \x01(\t\x12\x0e\n\x06length\x18\x03 \x01(\r\x12\x0b\n\x03uid\x18\x04 \x01(\r\x12\x0b\n\x03tag\x18\x05 \x01(\r\x12\x10\n\x08ip_proto\x18\x06 \x01(\r\x12\x11\n\ttcp_flags\x18\x07 \x01(\r\x12\x12\n\nlocal_port\x18\x08 \x01(\r\x12\x13\n\x0bremote_port\x18\t \x01(\r\x12\x11\n\ticmp_type\x18\n \x01(\r\x12\x11\n\ticmp_code\x18\x0b \x01(\r"\xea\x01\n\x13NetworkPacketBundle\x12\r\n\x03iid\x18\x01 \x01(\x04H\x00\x12\x32\n\x03\x63tx\x18\x02 \x01(\x0b\x32#.perfetto.protos.NetworkPacketEventH\x00\x12\x1d\n\x11packet_timestamps\x18\x03 \x03(\x04\x42\x02\x10\x01\x12\x1a\n\x0epacket_lengths\x18\x04 \x03(\rB\x02\x10\x01\x12\x15\n\rtotal_packets\x18\x05 \x01(\r\x12\x16\n\x0etotal_duration\x18\x06 \x01(\x04\x12\x14\n\x0ctotal_length\x18\x07 \x01(\x04\x42\x10\n\x0epacket_context"U\n\x14NetworkPacketContext\x12\x0b\n\x03iid\x18\x01 \x01(\x04\x12\x30\n\x03\x63tx\x18\x02 \x01(\x0b\x32#.perfetto.protos.NetworkPacketEvent"\xe8\x01\n\x0cPackagesList\x12;\n\x08packages\x18\x01 \x03(\x0b\x32).perfetto.protos.PackagesList.PackageInfo\x12\x13\n\x0bparse_error\x18\x02 \x01(\x08\x12\x12\n\nread_error\x18\x03 \x01(\x08\x1ar\n\x0bPackageInfo\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x0b\n\x03uid\x18\x02 \x01(\x04\x12\x12\n\ndebuggable\x18\x03 \x01(\x08\x12\x1e\n\x16profileable_from_shell\x18\x04 \x01(\x08\x12\x14\n\x0cversion_code\x18\x05 \x01(\x03"<\n\x10PixelModemEvents\x12\x0e\n\x06\x65vents\x18\x01 \x03(\x0c\x12\x18\n\x10\x65vent_time_nanos\x18\x02 \x03(\x04"+\n\x17PixelModemTokenDatabase\x12\x10\n\x08\x64\x61tabase\x18\x01 \x01(\x0c"\x9b\x01\n\x0fProtoLogMessage\x12\x12\n\nmessage_id\x18\x01 \x01(\x06\x12\x16\n\x0estr_param_iids\x18\x02 \x03(\r\x12\x15\n\rsint64_params\x18\x03 \x03(\x12\x12\x15\n\rdouble_params\x18\x04 \x03(\x01\x12\x16\n\x0e\x62oolean_params\x18\x05 \x03(\x05\x12\x16\n\x0estacktrace_iid\x18\x06 \x01(\r"\xd0\x02\n\x14ProtoLogViewerConfig\x12\x43\n\x08messages\x18\x01 \x03(\x0b\x32\x31.perfetto.protos.ProtoLogViewerConfig.MessageData\x12;\n\x06groups\x18\x02 \x03(\x0b\x32+.perfetto.protos.ProtoLogViewerConfig.Group\x1a\x85\x01\n\x0bMessageData\x12\x12\n\nmessage_id\x18\x01 \x01(\x06\x12\x0f\n\x07message\x18\x02 \x01(\t\x12-\n\x05level\x18\x03 \x01(\x0e\x32\x1e.perfetto.protos.ProtoLogLevel\x12\x10\n\x08group_id\x18\x04 \x01(\r\x12\x10\n\x08location\x18\x05 \x01(\t\x1a.\n\x05Group\x12\n\n\x02id\x18\x01 \x01(\r\x12\x0c\n\x04name\x18\x02 \x01(\t\x12\x0b\n\x03tag\x18\x03 \x01(\t"\x99\x04\n\x0fShellTransition\x12\n\n\x02id\x18\x01 \x01(\x05\x12\x16\n\x0e\x63reate_time_ns\x18\x02 \x01(\x03\x12\x14\n\x0csend_time_ns\x18\x03 \x01(\x03\x12\x18\n\x10\x64ispatch_time_ns\x18\x04 \x01(\x03\x12\x15\n\rmerge_time_ns\x18\x05 \x01(\x03\x12\x1d\n\x15merge_request_time_ns\x18\x06 \x01(\x03\x12\x1b\n\x13shell_abort_time_ns\x18\x07 \x01(\x03\x12\x18\n\x10wm_abort_time_ns\x18\x08 \x01(\x03\x12\x16\n\x0e\x66inish_time_ns\x18\t \x01(\x03\x12\x1c\n\x14start_transaction_id\x18\n \x01(\x04\x12\x1d\n\x15\x66inish_transaction_id\x18\x0b \x01(\x04\x12\x0f\n\x07handler\x18\x0c \x01(\x05\x12\x0c\n\x04type\x18\r \x01(\x05\x12\x38\n\x07targets\x18\x0e \x03(\x0b\x32\'.perfetto.protos.ShellTransition.Target\x12\x14\n\x0cmerge_target\x18\x0f \x01(\x05\x12\r\n\x05\x66lags\x18\x10 \x01(\x05\x12&\n\x1estarting_window_remove_time_ns\x18\x11 \x01(\x03\x1aJ\n\x06Target\x12\x0c\n\x04mode\x18\x01 \x01(\x05\x12\x10\n\x08layer_id\x18\x02 \x01(\x05\x12\x11\n\twindow_id\x18\x03 \x01(\x05\x12\r\n\x05\x66lags\x18\x04 \x01(\x05"M\n\x14ShellHandlerMappings\x12\x35\n\x07mapping\x18\x01 \x03(\x0b\x32$.perfetto.protos.ShellHandlerMapping"/\n\x13ShellHandlerMapping\x12\n\n\x02id\x18\x01 \x01(\x05\x12\x0c\n\x04name\x18\x02 \x01(\t"E\n\tRectProto\x12\x0c\n\x04left\x18\x01 \x01(\x05\x12\x0b\n\x03top\x18\x02 \x01(\x05\x12\r\n\x05right\x18\x03 \x01(\x05\x12\x0e\n\x06\x62ottom\x18\x04 \x01(\x05"=\n\x0bRegionProto\x12(\n\x04rect\x18\x02 \x03(\x0b\x32\x1a.perfetto.protos.RectProtoJ\x04\x08\x01\x10\x02"!\n\tSizeProto\x12\t\n\x01w\x18\x01 \x01(\x05\x12\t\n\x01h\x18\x02 \x01(\x05"V\n\x0eTransformProto\x12\x0c\n\x04\x64sdx\x18\x01 \x01(\x02\x12\x0c\n\x04\x64tdx\x18\x02 \x01(\x02\x12\x0c\n\x04\x64sdy\x18\x03 \x01(\x02\x12\x0c\n\x04\x64tdy\x18\x04 \x01(\x02\x12\x0c\n\x04type\x18\x05 \x01(\x05"8\n\nColorProto\x12\t\n\x01r\x18\x01 \x01(\x02\x12\t\n\x01g\x18\x02 \x01(\x02\x12\t\n\x01\x62\x18\x03 \x01(\x02\x12\t\n\x01\x61\x18\x04 \x01(\x02"\xbf\x04\n\x14InputWindowInfoProto\x12\x1b\n\x13layout_params_flags\x18\x01 \x01(\r\x12\x1a\n\x12layout_params_type\x18\x02 \x01(\x05\x12)\n\x05\x66rame\x18\x03 \x01(\x0b\x32\x1a.perfetto.protos.RectProto\x12\x36\n\x10touchable_region\x18\x04 \x01(\x0b\x32\x1c.perfetto.protos.RegionProto\x12\x15\n\rsurface_inset\x18\x05 \x01(\x05\x12\x0f\n\x07visible\x18\x06 \x01(\x08\x12\x1c\n\x10\x63\x61n_receive_keys\x18\x07 \x01(\x08\x42\x02\x18\x01\x12\x11\n\tfocusable\x18\x08 \x01(\x08\x12\x15\n\rhas_wallpaper\x18\t \x01(\x08\x12\x1b\n\x13global_scale_factor\x18\n \x01(\x02\x12\x1a\n\x0ewindow_x_scale\x18\x0b \x01(\x02\x42\x02\x18\x01\x12\x1a\n\x0ewindow_y_scale\x18\x0c \x01(\x02\x42\x02\x18\x01\x12\x15\n\rcrop_layer_id\x18\r \x01(\x05\x12*\n"replace_touchable_region_with_crop\x18\x0e \x01(\x08\x12\x39\n\x15touchable_region_crop\x18\x0f \x01(\x0b\x32\x1a.perfetto.protos.RectProto\x12\x32\n\ttransform\x18\x10 \x01(\x0b\x32\x1f.perfetto.protos.TransformProto\x12\x14\n\x0cinput_config\x18\x11 \x01(\r"\xd2\x01\n\nBlurRegion\x12\x13\n\x0b\x62lur_radius\x18\x01 \x01(\r\x12\x18\n\x10\x63orner_radius_tl\x18\x02 \x01(\r\x12\x18\n\x10\x63orner_radius_tr\x18\x03 \x01(\r\x12\x18\n\x10\x63orner_radius_bl\x18\x04 \x01(\r\x12\x18\n\x10\x63orner_radius_br\x18\x05 \x01(\x02\x12\r\n\x05\x61lpha\x18\x06 \x01(\x02\x12\x0c\n\x04left\x18\x07 \x01(\x05\x12\x0b\n\x03top\x18\x08 \x01(\x05\x12\r\n\x05right\x18\t \x01(\x05\x12\x0e\n\x06\x62ottom\x18\n \x01(\x05"&\n\x13\x43olorTransformProto\x12\x0f\n\x03val\x18\x01 \x03(\x02\x42\x02\x10\x01"\xd8\x01\n\x14LayersTraceFileProto\x12\x14\n\x0cmagic_number\x18\x01 \x01(\x06\x12\x33\n\x05\x65ntry\x18\x02 \x03(\x0b\x32$.perfetto.protos.LayersSnapshotProto\x12)\n!real_to_elapsed_time_offset_nanos\x18\x03 \x01(\x06"J\n\x0bMagicNumber\x12\x0b\n\x07INVALID\x10\x00\x12\x16\n\x0eMAGIC_NUMBER_L\x10\xcc\xb2\xc9\xa2\x05\x12\x16\n\x0eMAGIC_NUMBER_H\x10\xd2\x82\x8d\xaa\x04"\x83\x02\n\x13LayersSnapshotProto\x12\x1e\n\x16\x65lapsed_realtime_nanos\x18\x01 \x01(\x10\x12\r\n\x05where\x18\x02 \x01(\t\x12,\n\x06layers\x18\x03 \x01(\x0b\x32\x1c.perfetto.protos.LayersProto\x12\x10\n\x08hwc_blob\x18\x04 \x01(\t\x12"\n\x1a\x65xcludes_composition_state\x18\x05 \x01(\x08\x12\x16\n\x0emissed_entries\x18\x06 \x01(\r\x12/\n\x08\x64isplays\x18\x07 \x03(\x0b\x32\x1d.perfetto.protos.DisplayProto\x12\x10\n\x08vsync_id\x18\x08 \x01(\x03":\n\x0bLayersProto\x12+\n\x06layers\x18\x01 \x03(\x0b\x32\x1b.perfetto.protos.LayerProto"\x89\x02\n\x0c\x44isplayProto\x12\n\n\x02id\x18\x01 \x01(\x04\x12\x0c\n\x04name\x18\x02 \x01(\t\x12\x13\n\x0blayer_stack\x18\x03 \x01(\r\x12(\n\x04size\x18\x04 \x01(\x0b\x32\x1a.perfetto.protos.SizeProto\x12:\n\x16layer_stack_space_rect\x18\x05 \x01(\x0b\x32\x1a.perfetto.protos.RectProto\x12\x32\n\ttransform\x18\x06 \x01(\x0b\x32\x1f.perfetto.protos.TransformProto\x12\x12\n\nis_virtual\x18\x07 \x01(\x08\x12\r\n\x05\x64pi_x\x18\x08 \x01(\x01\x12\r\n\x05\x64pi_y\x18\t \x01(\x01"\x8a\x12\n\nLayerProto\x12\n\n\x02id\x18\x01 \x01(\x05\x12\x0c\n\x04name\x18\x02 \x01(\t\x12\x14\n\x08\x63hildren\x18\x03 \x03(\x05\x42\x02\x10\x01\x12\x15\n\trelatives\x18\x04 \x03(\x05\x42\x02\x10\x01\x12\x0c\n\x04type\x18\x05 \x01(\t\x12\x38\n\x12transparent_region\x18\x06 \x01(\x0b\x32\x1c.perfetto.protos.RegionProto\x12\x34\n\x0evisible_region\x18\x07 \x01(\x0b\x32\x1c.perfetto.protos.RegionProto\x12\x33\n\rdamage_region\x18\x08 \x01(\x0b\x32\x1c.perfetto.protos.RegionProto\x12\x13\n\x0blayer_stack\x18\t \x01(\r\x12\t\n\x01z\x18\n \x01(\x05\x12\x30\n\x08position\x18\x0b \x01(\x0b\x32\x1e.perfetto.protos.PositionProto\x12:\n\x12requested_position\x18\x0c \x01(\x0b\x32\x1e.perfetto.protos.PositionProto\x12(\n\x04size\x18\r \x01(\x0b\x32\x1a.perfetto.protos.SizeProto\x12(\n\x04\x63rop\x18\x0e \x01(\x0b\x32\x1a.perfetto.protos.RectProto\x12\x32\n\nfinal_crop\x18\x0f \x01(\x0b\x32\x1a.perfetto.protos.RectProtoB\x02\x18\x01\x12\x11\n\tis_opaque\x18\x10 \x01(\x08\x12\x12\n\ninvalidate\x18\x11 \x01(\x08\x12\x11\n\tdataspace\x18\x12 \x01(\t\x12\x14\n\x0cpixel_format\x18\x13 \x01(\t\x12*\n\x05\x63olor\x18\x14 \x01(\x0b\x32\x1b.perfetto.protos.ColorProto\x12\x34\n\x0frequested_color\x18\x15 \x01(\x0b\x32\x1b.perfetto.protos.ColorProto\x12\r\n\x05\x66lags\x18\x16 \x01(\r\x12\x32\n\ttransform\x18\x17 \x01(\x0b\x32\x1f.perfetto.protos.TransformProto\x12<\n\x13requested_transform\x18\x18 \x01(\x0b\x32\x1f.perfetto.protos.TransformProto\x12\x0e\n\x06parent\x18\x19 \x01(\x05\x12\x1b\n\x13z_order_relative_of\x18\x1a \x01(\x05\x12\x39\n\ractive_buffer\x18\x1b \x01(\x0b\x32".perfetto.protos.ActiveBufferProto\x12\x15\n\rqueued_frames\x18\x1c \x01(\x05\x12\x17\n\x0frefresh_pending\x18\x1d \x01(\x08\x12-\n\thwc_frame\x18\x1e \x01(\x0b\x32\x1a.perfetto.protos.RectProto\x12\x31\n\x08hwc_crop\x18\x1f \x01(\x0b\x32\x1f.perfetto.protos.FloatRectProto\x12\x15\n\rhwc_transform\x18 \x01(\x05\x12\x17\n\x0bwindow_type\x18! \x01(\x05\x42\x02\x18\x01\x12\x12\n\x06\x61pp_id\x18" \x01(\x05\x42\x02\x18\x01\x12\x41\n\x14hwc_composition_type\x18# \x01(\x0e\x32#.perfetto.protos.HwcCompositionType\x12\x14\n\x0cis_protected\x18$ \x01(\x08\x12\x12\n\ncurr_frame\x18% \x01(\x04\x12\x39\n\rbarrier_layer\x18& \x03(\x0b\x32".perfetto.protos.BarrierLayerProto\x12\x39\n\x10\x62uffer_transform\x18\' \x01(\x0b\x32\x1f.perfetto.protos.TransformProto\x12\x1e\n\x16\x65\x66\x66\x65\x63tive_scaling_mode\x18( \x01(\x05\x12\x15\n\rcorner_radius\x18) \x01(\x02\x12;\n\x08metadata\x18* \x03(\x0b\x32).perfetto.protos.LayerProto.MetadataEntry\x12<\n\x13\x65\x66\x66\x65\x63tive_transform\x18+ \x01(\x0b\x32\x1f.perfetto.protos.TransformProto\x12\x36\n\rsource_bounds\x18, \x01(\x0b\x32\x1f.perfetto.protos.FloatRectProto\x12/\n\x06\x62ounds\x18- \x01(\x0b\x32\x1f.perfetto.protos.FloatRectProto\x12\x36\n\rscreen_bounds\x18. \x01(\x0b\x32\x1f.perfetto.protos.FloatRectProto\x12@\n\x11input_window_info\x18/ \x01(\x0b\x32%.perfetto.protos.InputWindowInfoProto\x12;\n\x12\x63orner_radius_crop\x18\x30 \x01(\x0b\x32\x1f.perfetto.protos.FloatRectProto\x12\x15\n\rshadow_radius\x18\x31 \x01(\x02\x12=\n\x0f\x63olor_transform\x18\x32 \x01(\x0b\x32$.perfetto.protos.ColorTransformProto\x12\x16\n\x0eis_relative_of\x18\x33 \x01(\x08\x12\x1e\n\x16\x62\x61\x63kground_blur_radius\x18\x34 \x01(\x05\x12\x11\n\towner_uid\x18\x35 \x01(\r\x12\x31\n\x0c\x62lur_regions\x18\x36 \x03(\x0b\x32\x1b.perfetto.protos.BlurRegion\x12\x1a\n\x12is_trusted_overlay\x18\x37 \x01(\x08\x12\x1f\n\x17requested_corner_radius\x18\x38 \x01(\x02\x12\x35\n\x11\x64\x65stination_frame\x18\x39 \x01(\x0b\x32\x1a.perfetto.protos.RectProto\x12\x13\n\x0boriginal_id\x18: \x01(\r\x12\x38\n\x0ftrusted_overlay\x18; \x01(\x0e\x32\x1f.perfetto.protos.TrustedOverlay\x1a/\n\rMetadataEntry\x12\x0b\n\x03key\x18\x01 \x01(\x05\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01"%\n\rPositionProto\x12\t\n\x01x\x18\x01 \x01(\x02\x12\t\n\x01y\x18\x02 \x01(\x02"J\n\x0e\x46loatRectProto\x12\x0c\n\x04left\x18\x01 \x01(\x02\x12\x0b\n\x03top\x18\x02 \x01(\x02\x12\r\n\x05right\x18\x03 \x01(\x02\x12\x0e\n\x06\x62ottom\x18\x04 \x01(\x02"a\n\x11\x41\x63tiveBufferProto\x12\r\n\x05width\x18\x01 \x01(\r\x12\x0e\n\x06height\x18\x02 \x01(\r\x12\x0e\n\x06stride\x18\x03 \x01(\r\x12\x0e\n\x06\x66ormat\x18\x04 \x01(\x05\x12\r\n\x05usage\x18\x05 \x01(\x04"5\n\x11\x42\x61rrierLayerProto\x12\n\n\x02id\x18\x01 \x01(\x05\x12\x14\n\x0c\x66rame_number\x18\x02 \x01(\x04"\xeb\x01\n\x14TransactionTraceFile\x12\x14\n\x0cmagic_number\x18\x01 \x01(\x06\x12\x35\n\x05\x65ntry\x18\x02 \x03(\x0b\x32&.perfetto.protos.TransactionTraceEntry\x12)\n!real_to_elapsed_time_offset_nanos\x18\x03 \x01(\x06\x12\x0f\n\x07version\x18\x04 \x01(\r"J\n\x0bMagicNumber\x12\x0b\n\x07INVALID\x10\x00\x12\x16\n\x0eMAGIC_NUMBER_L\x10\xd4\x9c\xe1\xa2\x05\x12\x16\n\x0eMAGIC_NUMBER_H\x10\xd2\x82\x8d\xaa\x04"\x92\x03\n\x15TransactionTraceEntry\x12\x1e\n\x16\x65lapsed_realtime_nanos\x18\x01 \x01(\x03\x12\x10\n\x08vsync_id\x18\x02 \x01(\x03\x12\x37\n\x0ctransactions\x18\x03 \x03(\x0b\x32!.perfetto.protos.TransactionState\x12\x38\n\x0c\x61\x64\x64\x65\x64_layers\x18\x04 \x03(\x0b\x32".perfetto.protos.LayerCreationArgs\x12\x18\n\x10\x64\x65stroyed_layers\x18\x05 \x03(\r\x12\x35\n\x0e\x61\x64\x64\x65\x64_displays\x18\x06 \x03(\x0b\x32\x1d.perfetto.protos.DisplayState\x12\x18\n\x10removed_displays\x18\x07 \x03(\x05\x12\x1f\n\x17\x64\x65stroyed_layer_handles\x18\x08 \x03(\r\x12\x18\n\x10\x64isplays_changed\x18\t \x01(\x08\x12.\n\x08\x64isplays\x18\n \x03(\x0b\x32\x1c.perfetto.protos.DisplayInfo"\xce\x02\n\x0b\x44isplayInfo\x12\x13\n\x0blayer_stack\x18\x01 \x01(\r\x12\x12\n\ndisplay_id\x18\x02 \x01(\x05\x12\x15\n\rlogical_width\x18\x03 \x01(\x05\x12\x16\n\x0elogical_height\x18\x04 \x01(\x05\x12\x35\n\x11transform_inverse\x18\x05 \x01(\x0b\x32\x1a.perfetto.protos.Transform\x12-\n\ttransform\x18\x06 \x01(\x0b\x32\x1a.perfetto.protos.Transform\x12\x16\n\x0ereceives_input\x18\x07 \x01(\x08\x12\x11\n\tis_secure\x18\x08 \x01(\x08\x12\x12\n\nis_primary\x18\t \x01(\x08\x12\x12\n\nis_virtual\x18\n \x01(\x08\x12\x16\n\x0erotation_flags\x18\x0b \x01(\x05\x12\x16\n\x0etransform_hint\x18\x0c \x01(\x05"\xa1\x01\n\x11LayerCreationArgs\x12\x10\n\x08layer_id\x18\x01 \x01(\r\x12\x0c\n\x04name\x18\x02 \x01(\t\x12\r\n\x05\x66lags\x18\x03 \x01(\r\x12\x11\n\tparent_id\x18\x04 \x01(\r\x12\x16\n\x0emirror_from_id\x18\x05 \x01(\r\x12\x13\n\x0b\x61\x64\x64_to_root\x18\x06 \x01(\x08\x12\x1d\n\x15layer_stack_to_mirror\x18\x07 \x01(\r"[\n\tTransform\x12\x0c\n\x04\x64sdx\x18\x01 \x01(\x02\x12\x0c\n\x04\x64tdx\x18\x02 \x01(\x02\x12\x0c\n\x04\x64tdy\x18\x03 \x01(\x02\x12\x0c\n\x04\x64sdy\x18\x04 \x01(\x02\x12\n\n\x02tx\x18\x05 \x01(\x02\x12\n\n\x02ty\x18\x06 \x01(\x02"\x8d\x02\n\x10TransactionState\x12\x0b\n\x03pid\x18\x01 \x01(\x05\x12\x0b\n\x03uid\x18\x02 \x01(\x05\x12\x10\n\x08vsync_id\x18\x03 \x01(\x03\x12\x16\n\x0einput_event_id\x18\x04 \x01(\x05\x12\x11\n\tpost_time\x18\x05 \x01(\x03\x12\x16\n\x0etransaction_id\x18\x06 \x01(\x04\x12\x32\n\rlayer_changes\x18\x07 \x03(\x0b\x32\x1b.perfetto.protos.LayerState\x12\x36\n\x0f\x64isplay_changes\x18\x08 \x03(\x0b\x32\x1d.perfetto.protos.DisplayState\x12\x1e\n\x16merged_transaction_ids\x18\t \x03(\x04"\xc0 \n\nLayerState\x12\x10\n\x08layer_id\x18\x01 \x01(\r\x12\x0c\n\x04what\x18\x02 \x01(\x04\x12\t\n\x01x\x18\x03 \x01(\x02\x12\t\n\x01y\x18\x04 \x01(\x02\x12\t\n\x01z\x18\x05 \x01(\x05\x12\t\n\x01w\x18\x06 \x01(\r\x12\t\n\x01h\x18\x07 \x01(\r\x12\x13\n\x0blayer_stack\x18\x08 \x01(\r\x12\r\n\x05\x66lags\x18\t \x01(\r\x12\x0c\n\x04mask\x18\n \x01(\r\x12\x34\n\x06matrix\x18\x0b \x01(\x0b\x32$.perfetto.protos.LayerState.Matrix22\x12\x15\n\rcorner_radius\x18\x0c \x01(\x02\x12\x1e\n\x16\x62\x61\x63kground_blur_radius\x18\r \x01(\r\x12\x11\n\tparent_id\x18\x0e \x01(\r\x12\x1a\n\x12relative_parent_id\x18\x0f \x01(\r\x12\r\n\x05\x61lpha\x18\x10 \x01(\x02\x12\x31\n\x05\x63olor\x18\x11 \x01(\x0b\x32".perfetto.protos.LayerState.Color3\x12\x38\n\x12transparent_region\x18\x12 \x01(\x0b\x32\x1c.perfetto.protos.RegionProto\x12\x11\n\ttransform\x18\x13 \x01(\r\x12$\n\x1ctransform_to_display_inverse\x18\x14 \x01(\x08\x12(\n\x04\x63rop\x18\x15 \x01(\x0b\x32\x1a.perfetto.protos.RectProto\x12;\n\x0b\x62uffer_data\x18\x16 \x01(\x0b\x32&.perfetto.protos.LayerState.BufferData\x12\x0b\n\x03\x61pi\x18\x17 \x01(\x05\x12\x1b\n\x13has_sideband_stream\x18\x18 \x01(\x08\x12=\n\x0f\x63olor_transform\x18\x19 \x01(\x0b\x32$.perfetto.protos.ColorTransformProto\x12\x31\n\x0c\x62lur_regions\x18\x1a \x03(\x0b\x32\x1b.perfetto.protos.BlurRegion\x12\x42\n\x12window_info_handle\x18\x1b \x01(\x0b\x32&.perfetto.protos.LayerState.WindowInfo\x12\x16\n\x0e\x62g_color_alpha\x18\x1c \x01(\x02\x12\x1a\n\x12\x62g_color_dataspace\x18\x1d \x01(\x05\x12\x1c\n\x14\x63olor_space_agnostic\x18\x1e \x01(\x08\x12\x15\n\rshadow_radius\x18\x1f \x01(\x02\x12%\n\x1d\x66rame_rate_selection_priority\x18 \x01(\x05\x12\x12\n\nframe_rate\x18! \x01(\x02\x12 \n\x18\x66rame_rate_compatibility\x18" \x01(\x05\x12"\n\x1a\x63hange_frame_rate_strategy\x18# \x01(\x05\x12\x1c\n\x14\x66ixed_transform_hint\x18$ \x01(\r\x12\x14\n\x0c\x66rame_number\x18% \x01(\x04\x12\x14\n\x0c\x61uto_refresh\x18& \x01(\x08\x12\x1a\n\x12is_trusted_overlay\x18\' \x01(\x08\x12/\n\x0b\x62uffer_crop\x18( \x01(\x0b\x32\x1a.perfetto.protos.RectProto\x12\x35\n\x11\x64\x65stination_frame\x18) \x01(\x0b\x32\x1a.perfetto.protos.RectProto\x12\x42\n\x0f\x64rop_input_mode\x18* \x01(\x0e\x32).perfetto.protos.LayerState.DropInputMode\x12\x38\n\x0ftrusted_overlay\x18+ \x01(\x0e\x32\x1f.perfetto.protos.TrustedOverlay\x1a\x42\n\x08Matrix22\x12\x0c\n\x04\x64sdx\x18\x01 \x01(\x02\x12\x0c\n\x04\x64tdx\x18\x02 \x01(\x02\x12\x0c\n\x04\x64tdy\x18\x03 \x01(\x02\x12\x0c\n\x04\x64sdy\x18\x04 \x01(\x02\x1a)\n\x06\x43olor3\x12\t\n\x01r\x18\x01 \x01(\x02\x12\t\n\x01g\x18\x02 \x01(\x02\x12\t\n\x01\x62\x18\x03 \x01(\x02\x1a\x94\x06\n\nBufferData\x12\x11\n\tbuffer_id\x18\x01 \x01(\x04\x12\r\n\x05width\x18\x02 \x01(\r\x12\x0e\n\x06height\x18\x03 \x01(\r\x12\x14\n\x0c\x66rame_number\x18\x04 \x01(\x04\x12\r\n\x05\x66lags\x18\x05 \x01(\r\x12\x18\n\x10\x63\x61\x63hed_buffer_id\x18\x06 \x01(\x04\x12H\n\x0cpixel_format\x18\x07 \x01(\x0e\x32\x32.perfetto.protos.LayerState.BufferData.PixelFormat\x12\r\n\x05usage\x18\x08 \x01(\x04"o\n\x10\x42ufferDataChange\x12\x18\n\x14\x42ufferDataChangeNone\x10\x00\x12\x10\n\x0c\x66\x65nceChanged\x10\x01\x12\x16\n\x12\x66rameNumberChanged\x10\x02\x12\x17\n\x13\x63\x61\x63hedBufferChanged\x10\x04"\xca\x03\n\x0bPixelFormat\x12\x18\n\x14PIXEL_FORMAT_UNKNOWN\x10\x00\x12 \n\x13PIXEL_FORMAT_CUSTOM\x10\xfc\xff\xff\xff\xff\xff\xff\xff\xff\x01\x12%\n\x18PIXEL_FORMAT_TRANSLUCENT\x10\xfd\xff\xff\xff\xff\xff\xff\xff\xff\x01\x12%\n\x18PIXEL_FORMAT_TRANSPARENT\x10\xfe\xff\xff\xff\xff\xff\xff\xff\xff\x01\x12 \n\x13PIXEL_FORMAT_OPAQUE\x10\xff\xff\xff\xff\xff\xff\xff\xff\xff\x01\x12\x1a\n\x16PIXEL_FORMAT_RGBA_8888\x10\x01\x12\x1a\n\x16PIXEL_FORMAT_RGBX_8888\x10\x02\x12\x18\n\x14PIXEL_FORMAT_RGB_888\x10\x03\x12\x18\n\x14PIXEL_FORMAT_RGB_565\x10\x04\x12\x1a\n\x16PIXEL_FORMAT_BGRA_8888\x10\x05\x12\x1a\n\x16PIXEL_FORMAT_RGBA_5551\x10\x06\x12\x1a\n\x16PIXEL_FORMAT_RGBA_4444\x10\x07\x12\x1a\n\x16PIXEL_FORMAT_RGBA_FP16\x10\x16\x12\x1d\n\x19PIXEL_FORMAT_RGBA_1010102\x10+\x12\x14\n\x10PIXEL_FORMAT_R_8\x10\x38\x1a\x9e\x03\n\nWindowInfo\x12\x1b\n\x13layout_params_flags\x18\x01 \x01(\r\x12\x1a\n\x12layout_params_type\x18\x02 \x01(\x05\x12\x36\n\x10touchable_region\x18\x03 \x01(\x0b\x32\x1c.perfetto.protos.RegionProto\x12\x15\n\rsurface_inset\x18\x04 \x01(\x05\x12\x11\n\tfocusable\x18\x05 \x01(\x08\x12\x15\n\rhas_wallpaper\x18\x06 \x01(\x08\x12\x1b\n\x13global_scale_factor\x18\x07 \x01(\x02\x12\x15\n\rcrop_layer_id\x18\x08 \x01(\r\x12*\n"replace_touchable_region_with_crop\x18\t \x01(\x08\x12\x39\n\x15touchable_region_crop\x18\n \x01(\x0b\x32\x1a.perfetto.protos.RectProto\x12-\n\ttransform\x18\x0b \x01(\x0b\x32\x1a.perfetto.protos.Transform\x12\x14\n\x0cinput_config\x18\x0c \x01(\r"\xf8\x05\n\nChangesLsb\x12\x13\n\x0f\x65\x43hangesLsbNone\x10\x00\x12\x14\n\x10\x65PositionChanged\x10\x01\x12\x11\n\reLayerChanged\x10\x02\x12\x11\n\reAlphaChanged\x10\x08\x12\x12\n\x0e\x65MatrixChanged\x10\x10\x12\x1d\n\x19\x65TransparentRegionChanged\x10 \x12\x11\n\reFlagsChanged\x10@\x12\x17\n\x12\x65LayerStackChanged\x10\x80\x01\x12"\n\x1d\x65ReleaseBufferListenerChanged\x10\x80\x08\x12\x19\n\x14\x65ShadowRadiusChanged\x10\x80\x10\x12\x17\n\x12\x65\x42ufferCropChanged\x10\x80@\x12\x1b\n\x15\x65RelativeLayerChanged\x10\x80\x80\x01\x12\x0f\n\teReparent\x10\x80\x80\x02\x12\x13\n\reColorChanged\x10\x80\x80\x04\x12\x1d\n\x17\x65\x42ufferTransformChanged\x10\x80\x80\x10\x12\'\n!eTransformToDisplayInverseChanged\x10\x80\x80 \x12\x12\n\x0c\x65\x43ropChanged\x10\x80\x80@\x12\x15\n\x0e\x65\x42ufferChanged\x10\x80\x80\x80\x01\x12\x1b\n\x14\x65\x41\x63quireFenceChanged\x10\x80\x80\x80\x02\x12\x18\n\x11\x65\x44\x61taspaceChanged\x10\x80\x80\x80\x04\x12\x1a\n\x13\x65HdrMetadataChanged\x10\x80\x80\x80\x08\x12"\n\x1b\x65SurfaceDamageRegionChanged\x10\x80\x80\x80\x10\x12\x12\n\x0b\x65\x41piChanged\x10\x80\x80\x80 \x12\x1d\n\x16\x65SidebandStreamChanged\x10\x80\x80\x80@\x12\x1e\n\x16\x65\x43olorTransformChanged\x10\x80\x80\x80\x80\x01\x12$\n\x1c\x65HasListenerCallbacksChanged\x10\x80\x80\x80\x80\x02\x12\x19\n\x11\x65InputInfoChanged\x10\x80\x80\x80\x80\x04\x12!\n\x14\x65\x43ornerRadiusChanged\x10\x80\x80\x80\x80\xf8\xff\xff\xff\xff\x01"\xe1\x03\n\nChangesMsb\x12\x13\n\x0f\x65\x43hangesMsbNone\x10\x00\x12\x1c\n\x18\x65\x44\x65stinationFrameChanged\x10\x01\x12\x18\n\x14\x65\x43\x61\x63hedBufferChanged\x10\x02\x12\x1b\n\x17\x65\x42\x61\x63kgroundColorChanged\x10\x04\x12\x14\n\x10\x65MetadataChanged\x10\x08\x12\x1e\n\x1a\x65\x43olorSpaceAgnosticChanged\x10\x10\x12\x1f\n\x1b\x65\x46rameRateSelectionPriority\x10 \x12\x15\n\x11\x65\x46rameRateChanged\x10@\x12!\n\x1c\x65\x42\x61\x63kgroundBlurRadiusChanged\x10\x80\x01\x12\x18\n\x13\x65ProducerDisconnect\x10\x80\x02\x12\x1f\n\x1a\x65\x46ixedTransformHintChanged\x10\x80\x04\x12\x18\n\x13\x65\x46rameNumberChanged\x10\x80\x08\x12\x18\n\x13\x65\x42lurRegionsChanged\x10\x80\x10\x12\x18\n\x13\x65\x41utoRefreshChanged\x10\x80 \x12\x14\n\x0f\x65StretchChanged\x10\x80@\x12\x1c\n\x16\x65TrustedOverlayChanged\x10\x80\x80\x01\x12\x1b\n\x15\x65\x44ropInputModeChanged\x10\x80\x80\x02"\xa2\x01\n\x05\x46lags\x12\x0e\n\neFlagsNone\x10\x00\x12\x10\n\x0c\x65LayerHidden\x10\x01\x12\x10\n\x0c\x65LayerOpaque\x10\x02\x12\x18\n\x14\x65LayerSkipScreenshot\x10@\x12\x11\n\x0c\x65LayerSecure\x10\x80\x01\x12\x18\n\x13\x65\x45nableBackpressure\x10\x80\x02\x12\x1e\n\x19\x65LayerIsDisplayDecoration\x10\x80\x04"0\n\rDropInputMode\x12\x08\n\x04NONE\x10\x00\x12\x07\n\x03\x41LL\x10\x01\x12\x0c\n\x08OBSCURED\x10\x02"\x93\x03\n\x0c\x44isplayState\x12\n\n\x02id\x18\x01 \x01(\x05\x12\x0c\n\x04what\x18\x02 \x01(\r\x12\r\n\x05\x66lags\x18\x03 \x01(\r\x12\x13\n\x0blayer_stack\x18\x04 \x01(\r\x12\x13\n\x0borientation\x18\x05 \x01(\r\x12:\n\x16layer_stack_space_rect\x18\x06 \x01(\x0b\x32\x1a.perfetto.protos.RectProto\x12?\n\x1boriented_display_space_rect\x18\x07 \x01(\x0b\x32\x1a.perfetto.protos.RectProto\x12\r\n\x05width\x18\x08 \x01(\r\x12\x0e\n\x06height\x18\t \x01(\r"\x93\x01\n\x07\x43hanges\x12\x10\n\x0c\x65\x43hangesNone\x10\x00\x12\x13\n\x0f\x65SurfaceChanged\x10\x01\x12\x16\n\x12\x65LayerStackChanged\x10\x02\x12\x1d\n\x19\x65\x44isplayProjectionChanged\x10\x04\x12\x17\n\x13\x65\x44isplaySizeChanged\x10\x08\x12\x11\n\reFlagsChanged\x10\x10"\x1a\n\x12WinscopeExtensions*\x04\x08\x01\x10\x07"\xf2\x01\n\x17\x43hromeBenchmarkMetadata\x12\x1f\n\x17\x62\x65nchmark_start_time_us\x18\x01 \x01(\x03\x12\x19\n\x11story_run_time_us\x18\x02 \x01(\x03\x12\x16\n\x0e\x62\x65nchmark_name\x18\x03 \x01(\t\x12\x1d\n\x15\x62\x65nchmark_description\x18\x04 \x01(\t\x12\r\n\x05label\x18\x05 \x01(\t\x12\x12\n\nstory_name\x18\x06 \x01(\t\x12\x12\n\nstory_tags\x18\x07 \x03(\t\x12\x17\n\x0fstory_run_index\x18\x08 \x01(\x05\x12\x14\n\x0chad_failures\x18\t \x01(\x08"\x97\x02\n\x14\x43hromeMetadataPacket\x12O\n\x1b\x62\x61\x63kground_tracing_metadata\x18\x01 \x01(\x0b\x32*.perfetto.protos.BackgroundTracingMetadata\x12\x1b\n\x13\x63hrome_version_code\x18\x02 \x01(\x05\x12\x1a\n\x12\x65nabled_categories\x18\x03 \x01(\t\x12K\n\x12\x66ield_trial_hashes\x18\x04 \x03(\x0b\x32/.perfetto.protos.ChromeMetadataPacket.FinchHash\x1a(\n\tFinchHash\x12\x0c\n\x04name\x18\x01 \x01(\r\x12\r\n\x05group\x18\x02 \x01(\r"\x95\x08\n\x19\x42\x61\x63kgroundTracingMetadata\x12N\n\x0etriggered_rule\x18\x01 \x01(\x0b\x32\x36.perfetto.protos.BackgroundTracingMetadata.TriggerRule\x12L\n\x0c\x61\x63tive_rules\x18\x02 \x03(\x0b\x32\x36.perfetto.protos.BackgroundTracingMetadata.TriggerRule\x12\x1a\n\x12scenario_name_hash\x18\x03 \x01(\x07\x1a\xbd\x06\n\x0bTriggerRule\x12X\n\x0ctrigger_type\x18\x01 \x01(\x0e\x32\x42.perfetto.protos.BackgroundTracingMetadata.TriggerRule.TriggerType\x12\\\n\x0ehistogram_rule\x18\x02 \x01(\x0b\x32\x44.perfetto.protos.BackgroundTracingMetadata.TriggerRule.HistogramRule\x12T\n\nnamed_rule\x18\x03 \x01(\x0b\x32@.perfetto.protos.BackgroundTracingMetadata.TriggerRule.NamedRule\x12\x11\n\tname_hash\x18\x04 \x01(\x07\x1aj\n\rHistogramRule\x12\x1b\n\x13histogram_name_hash\x18\x01 \x01(\x06\x12\x1d\n\x15histogram_min_trigger\x18\x02 \x01(\x03\x12\x1d\n\x15histogram_max_trigger\x18\x03 \x01(\x03\x1a\x96\x02\n\tNamedRule\x12^\n\nevent_type\x18\x01 \x01(\x0e\x32J.perfetto.protos.BackgroundTracingMetadata.TriggerRule.NamedRule.EventType\x12!\n\x19\x63ontent_trigger_name_hash\x18\x02 \x01(\x06"\x85\x01\n\tEventType\x12\x0f\n\x0bUNSPECIFIED\x10\x00\x12\x13\n\x0fSESSION_RESTORE\x10\x01\x12\x0e\n\nNAVIGATION\x10\x02\x12\x0b\n\x07STARTUP\x10\x03\x12\x10\n\x0cREACHED_CODE\x10\x04\x12\x13\n\x0f\x43ONTENT_TRIGGER\x10\x05\x12\x0e\n\tTEST_RULE\x10\xe8\x07"\x87\x01\n\x0bTriggerType\x12\x17\n\x13TRIGGER_UNSPECIFIED\x10\x00\x12\x36\n2MONITOR_AND_DUMP_WHEN_SPECIFIC_HISTOGRAM_AND_VALUE\x10\x01\x12\'\n#MONITOR_AND_DUMP_WHEN_TRIGGER_NAMED\x10\x02"\xd3\x02\n\x11\x43hromeTracedValue\x12\x42\n\x0bnested_type\x18\x01 \x01(\x0e\x32-.perfetto.protos.ChromeTracedValue.NestedType\x12\x11\n\tdict_keys\x18\x02 \x03(\t\x12\x37\n\x0b\x64ict_values\x18\x03 \x03(\x0b\x32".perfetto.protos.ChromeTracedValue\x12\x38\n\x0c\x61rray_values\x18\x04 \x03(\x0b\x32".perfetto.protos.ChromeTracedValue\x12\x11\n\tint_value\x18\x05 \x01(\x05\x12\x14\n\x0c\x64ouble_value\x18\x06 \x01(\x01\x12\x12\n\nbool_value\x18\x07 \x01(\x08\x12\x14\n\x0cstring_value\x18\x08 \x01(\t"!\n\nNestedType\x12\x08\n\x04\x44ICT\x10\x00\x12\t\n\x05\x41RRAY\x10\x01"6\n\x16\x43hromeStringTableEntry\x12\r\n\x05value\x18\x01 \x01(\t\x12\r\n\x05index\x18\x02 \x01(\x05"\x81\x05\n\x10\x43hromeTraceEvent\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x11\n\ttimestamp\x18\x02 \x01(\x03\x12\r\n\x05phase\x18\x03 \x01(\x05\x12\x11\n\tthread_id\x18\x04 \x01(\x05\x12\x10\n\x08\x64uration\x18\x05 \x01(\x03\x12\x17\n\x0fthread_duration\x18\x06 \x01(\x03\x12\r\n\x05scope\x18\x07 \x01(\t\x12\n\n\x02id\x18\x08 \x01(\x04\x12\r\n\x05\x66lags\x18\t \x01(\r\x12\x1b\n\x13\x63\x61tegory_group_name\x18\n \x01(\t\x12\x12\n\nprocess_id\x18\x0b \x01(\x05\x12\x18\n\x10thread_timestamp\x18\x0c \x01(\x03\x12\x0f\n\x07\x62ind_id\x18\r \x01(\x04\x12\x33\n\x04\x61rgs\x18\x0e \x03(\x0b\x32%.perfetto.protos.ChromeTraceEvent.Arg\x12\x12\n\nname_index\x18\x0f \x01(\r\x12!\n\x19\x63\x61tegory_group_name_index\x18\x10 \x01(\r\x1a\x8c\x02\n\x03\x41rg\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x14\n\nbool_value\x18\x02 \x01(\x08H\x00\x12\x14\n\nuint_value\x18\x03 \x01(\x04H\x00\x12\x13\n\tint_value\x18\x04 \x01(\x03H\x00\x12\x16\n\x0c\x64ouble_value\x18\x05 \x01(\x01H\x00\x12\x16\n\x0cstring_value\x18\x06 \x01(\tH\x00\x12\x17\n\rpointer_value\x18\x07 \x01(\x04H\x00\x12\x14\n\njson_value\x18\x08 \x01(\tH\x00\x12:\n\x0ctraced_value\x18\n \x01(\x0b\x32".perfetto.protos.ChromeTracedValueH\x00\x12\x12\n\nname_index\x18\t \x01(\rB\x07\n\x05value"\x80\x01\n\x0e\x43hromeMetadata\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x16\n\x0cstring_value\x18\x02 \x01(\tH\x00\x12\x14\n\nbool_value\x18\x03 \x01(\x08H\x00\x12\x13\n\tint_value\x18\x04 \x01(\x03H\x00\x12\x14\n\njson_value\x18\x05 \x01(\tH\x00\x42\x07\n\x05value"\x94\x01\n\x15\x43hromeLegacyJsonTrace\x12>\n\x04type\x18\x01 \x01(\x0e\x32\x30.perfetto.protos.ChromeLegacyJsonTrace.TraceType\x12\x0c\n\x04\x64\x61ta\x18\x02 \x01(\t"-\n\tTraceType\x12\x0e\n\nUSER_TRACE\x10\x00\x12\x10\n\x0cSYSTEM_TRACE\x10\x01"\xa7\x02\n\x11\x43hromeEventBundle\x12;\n\x0ctrace_events\x18\x01 \x03(\x0b\x32!.perfetto.protos.ChromeTraceEventB\x02\x18\x01\x12\x31\n\x08metadata\x18\x02 \x03(\x0b\x32\x1f.perfetto.protos.ChromeMetadata\x12\x1c\n\x14legacy_ftrace_output\x18\x04 \x03(\t\x12\x41\n\x11legacy_json_trace\x18\x05 \x03(\x0b\x32&.perfetto.protos.ChromeLegacyJsonTrace\x12\x41\n\x0cstring_table\x18\x03 \x03(\x0b\x32\'.perfetto.protos.ChromeStringTableEntryB\x02\x18\x01"@\n\rChromeTrigger\x12\x14\n\x0ctrigger_name\x18\x01 \x01(\t\x12\x19\n\x11trigger_name_hash\x18\x02 \x01(\x07"V\n\x08V8String\x12\x10\n\x06latin1\x18\x01 \x01(\x0cH\x00\x12\x12\n\x08utf16_le\x18\x02 \x01(\x0cH\x00\x12\x12\n\x08utf16_be\x18\x03 \x01(\x0cH\x00\x42\x10\n\x0e\x65ncoded_string"k\n\x10InternedV8String\x12\x0b\n\x03iid\x18\x01 \x01(\x04\x12\x10\n\x06latin1\x18\x02 \x01(\x0cH\x00\x12\x12\n\x08utf16_le\x18\x03 \x01(\x0cH\x00\x12\x12\n\x08utf16_be\x18\x04 \x01(\x0cH\x00\x42\x10\n\x0e\x65ncoded_string"\xc5\x02\n\x12InternedV8JsScript\x12\x0b\n\x03iid\x18\x01 \x01(\x04\x12\x11\n\tscript_id\x18\x02 \x01(\x05\x12\x36\n\x04type\x18\x03 \x01(\x0e\x32(.perfetto.protos.InternedV8JsScript.Type\x12\'\n\x04name\x18\x04 \x01(\x0b\x32\x19.perfetto.protos.V8String\x12)\n\x06source\x18\x05 \x01(\x0b\x32\x19.perfetto.protos.V8String"\x82\x01\n\x04Type\x12\x10\n\x0cTYPE_UNKNOWN\x10\x00\x12\x0f\n\x0bTYPE_NORMAL\x10\x01\x12\r\n\tTYPE_EVAL\x10\x02\x12\x0f\n\x0bTYPE_MODULE\x10\x03\x12\x0f\n\x0bTYPE_NATIVE\x10\x04\x12\x12\n\x0eTYPE_EXTENSION\x10\x05\x12\x12\n\x0eTYPE_INSPECTOR\x10\x06"C\n\x14InternedV8WasmScript\x12\x0b\n\x03iid\x18\x01 \x01(\x04\x12\x11\n\tscript_id\x18\x02 \x01(\x05\x12\x0b\n\x03url\x18\x03 \x01(\t"\xb7\x08\n\x14InternedV8JsFunction\x12\x0b\n\x03iid\x18\x01 \x01(\x04\x12\x1f\n\x17v8_js_function_name_iid\x18\x02 \x01(\x04\x12\x18\n\x10v8_js_script_iid\x18\x03 \x01(\x04\x12\x13\n\x0bis_toplevel\x18\x04 \x01(\x08\x12\x38\n\x04kind\x18\x05 \x01(\x0e\x32*.perfetto.protos.InternedV8JsFunction.Kind\x12\x13\n\x0b\x62yte_offset\x18\x06 \x01(\r"\xf2\x06\n\x04Kind\x12\x10\n\x0cKIND_UNKNOWN\x10\x00\x12\x18\n\x14KIND_NORMAL_FUNCTION\x10\x01\x12\x0f\n\x0bKIND_MODULE\x10\x02\x12\x15\n\x11KIND_ASYNC_MODULE\x10\x03\x12\x19\n\x15KIND_BASE_CONSTRUCTOR\x10\x04\x12!\n\x1dKIND_DEFAULT_BASE_CONSTRUCTOR\x10\x05\x12$\n KIND_DEFAULT_DERIVED_CONSTRUCTOR\x10\x06\x12\x1c\n\x18KIND_DERIVED_CONSTRUCTOR\x10\x07\x12\x18\n\x14KIND_GETTER_FUNCTION\x10\x08\x12\x1f\n\x1bKIND_STATIC_GETTER_FUNCTION\x10\t\x12\x18\n\x14KIND_SETTER_FUNCTION\x10\n\x12\x1f\n\x1bKIND_STATIC_SETTER_FUNCTION\x10\x0b\x12\x17\n\x13KIND_ARROW_FUNCTION\x10\x0c\x12\x1d\n\x19KIND_ASYNC_ARROW_FUNCTION\x10\r\x12\x17\n\x13KIND_ASYNC_FUNCTION\x10\x0e\x12\x1d\n\x19KIND_ASYNC_CONCISE_METHOD\x10\x0f\x12$\n KIND_STATIC_ASYNC_CONCISE_METHOD\x10\x10\x12\'\n#KIND_ASYNC_CONCISE_GENERATOR_METHOD\x10\x11\x12.\n*KIND_STATIC_ASYNC_CONCISE_GENERATOR_METHOD\x10\x12\x12!\n\x1dKIND_ASYNC_GENERATOR_FUNCTION\x10\x13\x12\x1b\n\x17KIND_GENERATOR_FUNCTION\x10\x14\x12!\n\x1dKIND_CONCISE_GENERATOR_METHOD\x10\x15\x12(\n$KIND_STATIC_CONCISE_GENERATOR_METHOD\x10\x16\x12\x17\n\x13KIND_CONCISE_METHOD\x10\x17\x12\x1e\n\x1aKIND_STATIC_CONCISE_METHOD\x10\x18\x12+\n\'KIND_CLASS_MEMBERS_INITIALIZER_FUNCTION\x10\x19\x12*\n&KIND_CLASS_STATIC_INITIALIZER_FUNCTION\x10\x1a\x12\x10\n\x0cKIND_INVALID\x10\x1b"\xc7\x02\n\x11InternedV8Isolate\x12\x0b\n\x03iid\x18\x01 \x01(\x04\x12\x0b\n\x03pid\x18\x02 \x01(\r\x12\x12\n\nisolate_id\x18\x03 \x01(\x05\x12@\n\ncode_range\x18\x04 \x01(\x0b\x32,.perfetto.protos.InternedV8Isolate.CodeRange\x12(\n embedded_blob_code_start_address\x18\x05 \x01(\x04\x12\x1f\n\x17\x65mbedded_blob_code_size\x18\x06 \x01(\x04\x1aw\n\tCodeRange\x12\x14\n\x0c\x62\x61se_address\x18\x01 \x01(\x04\x12\x0c\n\x04size\x18\x02 \x01(\x04\x12-\n%embedded_blob_code_copy_start_address\x18\x03 \x01(\x04\x12\x17\n\x0fis_process_wide\x18\x04 \x01(\x08"\xea\x02\n\x08V8JsCode\x12\x16\n\x0ev8_isolate_iid\x18\x01 \x01(\x04\x12\x0b\n\x03tid\x18\x02 \x01(\r\x12\x1a\n\x12v8_js_function_iid\x18\x03 \x01(\x04\x12,\n\x04tier\x18\x04 \x01(\x0e\x32\x1e.perfetto.protos.V8JsCode.Tier\x12\x19\n\x11instruction_start\x18\x05 \x01(\x04\x12\x1e\n\x16instruction_size_bytes\x18\x06 \x01(\x04\x12\x16\n\x0cmachine_code\x18\x07 \x01(\x0cH\x00\x12\x12\n\x08\x62ytecode\x18\x08 \x01(\x0cH\x00"x\n\x04Tier\x12\x10\n\x0cTIER_UNKNOWN\x10\x00\x12\x11\n\rTIER_IGNITION\x10\x01\x12\x12\n\x0eTIER_SPARKPLUG\x10\x02\x12\x0f\n\x0bTIER_MAGLEV\x10\x03\x12\x13\n\x0fTIER_TURBOSHAFT\x10\x04\x12\x11\n\rTIER_TURBOFAN\x10\x05\x42\x0e\n\x0cinstructions"\xe1\x03\n\x0eV8InternalCode\x12\x16\n\x0ev8_isolate_iid\x18\x01 \x01(\x04\x12\x0b\n\x03tid\x18\x02 \x01(\r\x12\x0c\n\x04name\x18\x03 \x01(\t\x12\x32\n\x04type\x18\x04 \x01(\x0e\x32$.perfetto.protos.V8InternalCode.Type\x12\x12\n\nbuiltin_id\x18\x05 \x01(\x05\x12\x19\n\x11instruction_start\x18\x06 \x01(\x04\x12\x1e\n\x16instruction_size_bytes\x18\x07 \x01(\x04\x12\x14\n\x0cmachine_code\x18\x08 \x01(\x0c"\x82\x02\n\x04Type\x12\x10\n\x0cTYPE_UNKNOWN\x10\x00\x12\x19\n\x15TYPE_BYTECODE_HANDLER\x10\x01\x12\x14\n\x10TYPE_FOR_TESTING\x10\x02\x12\x10\n\x0cTYPE_BUILTIN\x10\x03\x12\x16\n\x12TYPE_WASM_FUNCTION\x10\x04\x12\x1e\n\x1aTYPE_WASM_TO_CAPI_FUNCTION\x10\x05\x12\x1c\n\x18TYPE_WASM_TO_JS_FUNCTION\x10\x06\x12\x1c\n\x18TYPE_JS_TO_WASM_FUNCTION\x10\x07\x12\x1a\n\x16TYPE_JS_TO_JS_FUNCTION\x10\x08\x12\x15\n\x11TYPE_C_WASM_ENTRY\x10\t"\xc3\x02\n\nV8WasmCode\x12\x16\n\x0ev8_isolate_iid\x18\x01 \x01(\x04\x12\x0b\n\x03tid\x18\x02 \x01(\r\x12\x1a\n\x12v8_wasm_script_iid\x18\x03 \x01(\x04\x12\x15\n\rfunction_name\x18\x04 \x01(\t\x12.\n\x04tier\x18\x05 \x01(\x0e\x32 .perfetto.protos.V8WasmCode.Tier\x12\x1d\n\x15\x63ode_offset_in_module\x18\x06 \x01(\x05\x12\x19\n\x11instruction_start\x18\x07 \x01(\x04\x12\x1e\n\x16instruction_size_bytes\x18\x08 \x01(\x04\x12\x14\n\x0cmachine_code\x18\t \x01(\x0c"=\n\x04Tier\x12\x10\n\x0cTIER_UNKNOWN\x10\x00\x12\x10\n\x0cTIER_LIFTOFF\x10\x01\x12\x11\n\rTIER_TURBOFAN\x10\x02"\xb0\x01\n\x0cV8RegExpCode\x12\x16\n\x0ev8_isolate_iid\x18\x01 \x01(\x04\x12\x0b\n\x03tid\x18\x02 \x01(\r\x12*\n\x07pattern\x18\x03 \x01(\x0b\x32\x19.perfetto.protos.V8String\x12\x19\n\x11instruction_start\x18\x04 \x01(\x04\x12\x1e\n\x16instruction_size_bytes\x18\x05 \x01(\x04\x12\x14\n\x0cmachine_code\x18\x06 \x01(\x0c"\xe1\x01\n\nV8CodeMove\x12\x13\n\x0bisolate_iid\x18\x01 \x01(\x04\x12\x0b\n\x03tid\x18\x02 \x01(\r\x12&\n\x1e\x66rom_instruction_start_address\x18\x03 \x01(\x04\x12$\n\x1cto_instruction_start_address\x18\x04 \x01(\x04\x12\x1e\n\x16instruction_size_bytes\x18\x05 \x01(\x04\x12\x19\n\x0fto_machine_code\x18\x06 \x01(\x0cH\x00\x12\x15\n\x0bto_bytecode\x18\x07 \x01(\x0cH\x00\x42\x11\n\x0fto_instructions"\x1d\n\x0eV8CodeDefaults\x12\x0b\n\x03tid\x18\x01 \x01(\r"\x92\x03\n\rClockSnapshot\x12\x34\n\x06\x63locks\x18\x01 \x03(\x0b\x32$.perfetto.protos.ClockSnapshot.Clock\x12:\n\x13primary_trace_clock\x18\x02 \x01(\x0e\x32\x1d.perfetto.protos.BuiltinClock\x1a\x8e\x02\n\x05\x43lock\x12\x10\n\x08\x63lock_id\x18\x01 \x01(\r\x12\x11\n\ttimestamp\x18\x02 \x01(\x04\x12\x16\n\x0eis_incremental\x18\x03 \x01(\x08\x12\x1a\n\x12unit_multiplier_ns\x18\x04 \x01(\x04"\xab\x01\n\rBuiltinClocks\x12\x0b\n\x07UNKNOWN\x10\x00\x12\x0c\n\x08REALTIME\x10\x01\x12\x13\n\x0fREALTIME_COARSE\x10\x02\x12\r\n\tMONOTONIC\x10\x03\x12\x14\n\x10MONOTONIC_COARSE\x10\x04\x12\x11\n\rMONOTONIC_RAW\x10\x05\x12\x0c\n\x08\x42OOTTIME\x10\x06\x12\x18\n\x14\x42UILTIN_CLOCK_MAX_ID\x10?"\x04\x08\x07\x10\x07"\x04\x08\x08\x10\x08"\xf8\n\n\x0f\x43SwitchEtwEvent\x12\x15\n\rnew_thread_id\x18\x01 \x01(\r\x12\x15\n\rold_thread_id\x18\x02 \x01(\r\x12\x1b\n\x13new_thread_priority\x18\x03 \x01(\x11\x12\x1b\n\x13old_thread_priority\x18\x04 \x01(\x11\x12\x18\n\x10previous_c_state\x18\x05 \x01(\r\x12T\n\x16old_thread_wait_reason\x18\x06 \x01(\x0e\x32\x34.perfetto.protos.CSwitchEtwEvent.OldThreadWaitReason\x12P\n\x14old_thread_wait_mode\x18\x07 \x01(\x0e\x32\x32.perfetto.protos.CSwitchEtwEvent.OldThreadWaitMode\x12I\n\x10old_thread_state\x18\x08 \x01(\x0e\x32/.perfetto.protos.CSwitchEtwEvent.OldThreadState\x12\'\n\x1fold_thread_wait_ideal_processor\x18\t \x01(\x11\x12\x1c\n\x14new_thread_wait_time\x18\n \x01(\r"\xe9\x05\n\x13OldThreadWaitReason\x12\r\n\tEXECUTIVE\x10\x00\x12\r\n\tFREE_PAGE\x10\x01\x12\x0b\n\x07PAGE_IN\x10\x02\x12\x13\n\x0fPOOL_ALLOCATION\x10\x03\x12\x13\n\x0f\x44\x45LAY_EXECUTION\x10\x04\x12\x0b\n\x07SUSPEND\x10\x05\x12\x10\n\x0cUSER_REQUEST\x10\x06\x12\x10\n\x0cWR_EXECUTIVE\x10\x07\x12\x10\n\x0cWR_FREE_PAGE\x10\x08\x12\x0e\n\nWR_PAGE_IN\x10\t\x12\x16\n\x12WR_POOL_ALLOCATION\x10\n\x12\x16\n\x12WR_DELAY_EXECUTION\x10\x0b\x12\x10\n\x0cWR_SUSPENDED\x10\x0c\x12\x13\n\x0fWR_USER_REQUEST\x10\r\x12\x11\n\rWR_EVENT_PAIR\x10\x0e\x12\x0c\n\x08WR_QUEUE\x10\x0f\x12\x13\n\x0fWR_LPC_RECEIVER\x10\x10\x12\x10\n\x0cWR_LPC_REPLY\x10\x11\x12\x15\n\x11WR_VIRTUAL_MEMORY\x10\x12\x12\x0f\n\x0bWR_PAGE_OUT\x10\x13\x12\x12\n\x0eWR_RENDEZ_VOUS\x10\x14\x12\x12\n\x0eWR_KEYED_EVENT\x10\x15\x12\x11\n\rWR_TERMINATED\x10\x16\x12\x16\n\x12WR_PROCESS_IN_SWAP\x10\x17\x12\x17\n\x13WR_CPU_RATE_CONTROL\x10\x18\x12\x14\n\x10WR_CALLOUT_STACK\x10\x19\x12\r\n\tWR_KERNEL\x10\x1a\x12\x0f\n\x0bWR_RESOURCE\x10\x1b\x12\x10\n\x0cWR_PUSH_LOCK\x10\x1c\x12\x0c\n\x08WR_MUTEX\x10\x1d\x12\x12\n\x0eWR_QUANTUM_END\x10\x1e\x12\x13\n\x0fWR_DISPATCH_INT\x10\x1f\x12\x10\n\x0cWR_PREEMPTED\x10 \x12\x16\n\x12WR_YIELD_EXECUTION\x10!\x12\x11\n\rWR_FAST_MUTEX\x10"\x12\x12\n\x0eWR_GUARD_MUTEX\x10#\x12\x0e\n\nWR_RUNDOWN\x10$\x12\x17\n\x13MAXIMUM_WAIT_REASON\x10%"3\n\x11OldThreadWaitMode\x12\x0f\n\x0bKERNEL_MODE\x10\x00\x12\r\n\tUSER_MODE\x10\x01"\x87\x01\n\x0eOldThreadState\x12\x0f\n\x0bINITIALIZED\x10\x00\x12\t\n\x05READY\x10\x01\x12\x0b\n\x07RUNNING\x10\x02\x12\x0b\n\x07STANDBY\x10\x03\x12\x0e\n\nTERMINATED\x10\x04\x12\x0b\n\x07WAITING\x10\x05\x12\x0e\n\nTRANSITION\x10\x06\x12\x12\n\x0e\x44\x45\x46\x45RRED_READY\x10\x07"\xa2\x03\n\x13ReadyThreadEtwEvent\x12\x13\n\x0bt_thread_id\x18\x01 \x01(\r\x12H\n\radjust_reason\x18\x02 \x01(\x0e\x32\x31.perfetto.protos.ReadyThreadEtwEvent.AdjustReason\x12\x18\n\x10\x61\x64just_increment\x18\x03 \x01(\x11\x12<\n\x04\x66lag\x18\x04 \x01(\x0e\x32..perfetto.protos.ReadyThreadEtwEvent.TraceFlag"X\n\x0c\x41\x64justReason\x12\x18\n\x14IGNORE_THE_INCREMENT\x10\x00\x12\x13\n\x0f\x41PPLY_INCREMENT\x10\x01\x12\x19\n\x15\x41PPLY_INCREMENT_BOOST\x10\x02"z\n\tTraceFlag\x12\x1a\n\x16TRACE_FLAG_UNSPECIFIED\x10\x00\x12\x12\n\x0eTHREAD_READIED\x10\x01\x12\x1c\n\x18KERNEL_STACK_SWAPPED_OUT\x10\x02\x12\x1f\n\x1bPROCESS_ADDRESS_SWAPPED_OUT\x10\x04"\xac\x01\n\rEtwTraceEvent\x12\x11\n\ttimestamp\x18\x01 \x01(\x04\x12\x0b\n\x03\x63pu\x18\x04 \x01(\r\x12\x34\n\x08\x63_switch\x18\x02 \x01(\x0b\x32 .perfetto.protos.CSwitchEtwEventH\x00\x12<\n\x0cready_thread\x18\x03 \x01(\x0b\x32$.perfetto.protos.ReadyThreadEtwEventH\x00\x42\x07\n\x05\x65vent"Q\n\x13\x45twTraceEventBundle\x12\x0b\n\x03\x63pu\x18\x01 \x01(\r\x12-\n\x05\x65vent\x18\x02 \x03(\x0b\x32\x1e.perfetto.protos.EtwTraceEvent"G\n\x11\x46ileDescriptorSet\x12\x32\n\x04\x66ile\x18\x01 \x03(\x0b\x32$.perfetto.protos.FileDescriptorProto"\xbf\x02\n\x13\x46ileDescriptorProto\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x0f\n\x07package\x18\x02 \x01(\t\x12\x12\n\ndependency\x18\x03 \x03(\t\x12\x19\n\x11public_dependency\x18\n \x03(\x05\x12\x17\n\x0fweak_dependency\x18\x0b \x03(\x05\x12\x36\n\x0cmessage_type\x18\x04 \x03(\x0b\x32 .perfetto.protos.DescriptorProto\x12\x37\n\tenum_type\x18\x05 \x03(\x0b\x32$.perfetto.protos.EnumDescriptorProto\x12\x38\n\textension\x18\x07 \x03(\x0b\x32%.perfetto.protos.FieldDescriptorProtoJ\x04\x08\x06\x10\x07J\x04\x08\x08\x10\tJ\x04\x08\t\x10\nJ\x04\x08\x0c\x10\r"\xd2\x03\n\x0f\x44\x65scriptorProto\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x34\n\x05\x66ield\x18\x02 \x03(\x0b\x32%.perfetto.protos.FieldDescriptorProto\x12\x38\n\textension\x18\x06 \x03(\x0b\x32%.perfetto.protos.FieldDescriptorProto\x12\x35\n\x0bnested_type\x18\x03 \x03(\x0b\x32 .perfetto.protos.DescriptorProto\x12\x37\n\tenum_type\x18\x04 \x03(\x0b\x32$.perfetto.protos.EnumDescriptorProto\x12\x39\n\noneof_decl\x18\x08 \x03(\x0b\x32%.perfetto.protos.OneofDescriptorProto\x12\x46\n\x0ereserved_range\x18\t \x03(\x0b\x32..perfetto.protos.DescriptorProto.ReservedRange\x12\x15\n\rreserved_name\x18\n \x03(\t\x1a+\n\rReservedRange\x12\r\n\x05start\x18\x01 \x01(\x05\x12\x0b\n\x03\x65nd\x18\x02 \x01(\x05J\x04\x08\x05\x10\x06J\x04\x08\x07\x10\x08"\x9e\x02\n\x13UninterpretedOption\x12;\n\x04name\x18\x02 \x03(\x0b\x32-.perfetto.protos.UninterpretedOption.NamePart\x12\x18\n\x10identifier_value\x18\x03 \x01(\t\x12\x1a\n\x12positive_int_value\x18\x04 \x01(\x04\x12\x1a\n\x12negative_int_value\x18\x05 \x01(\x03\x12\x14\n\x0c\x64ouble_value\x18\x06 \x01(\x01\x12\x14\n\x0cstring_value\x18\x07 \x01(\x0c\x12\x17\n\x0f\x61ggregate_value\x18\x08 \x01(\t\x1a\x33\n\x08NamePart\x12\x11\n\tname_part\x18\x01 \x01(\t\x12\x14\n\x0cis_extension\x18\x02 \x01(\x08"c\n\x0c\x46ieldOptions\x12\x0e\n\x06packed\x18\x02 \x01(\x08\x12\x43\n\x14uninterpreted_option\x18\xe7\x07 \x03(\x0b\x32$.perfetto.protos.UninterpretedOption"\xaf\x05\n\x14\x46ieldDescriptorProto\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x0e\n\x06number\x18\x03 \x01(\x05\x12:\n\x05label\x18\x04 \x01(\x0e\x32+.perfetto.protos.FieldDescriptorProto.Label\x12\x38\n\x04type\x18\x05 \x01(\x0e\x32*.perfetto.protos.FieldDescriptorProto.Type\x12\x11\n\ttype_name\x18\x06 \x01(\t\x12\x10\n\x08\x65xtendee\x18\x02 \x01(\t\x12\x15\n\rdefault_value\x18\x07 \x01(\t\x12.\n\x07options\x18\x08 \x01(\x0b\x32\x1d.perfetto.protos.FieldOptions\x12\x13\n\x0boneof_index\x18\t \x01(\x05"\xb6\x02\n\x04Type\x12\x0f\n\x0bTYPE_DOUBLE\x10\x01\x12\x0e\n\nTYPE_FLOAT\x10\x02\x12\x0e\n\nTYPE_INT64\x10\x03\x12\x0f\n\x0bTYPE_UINT64\x10\x04\x12\x0e\n\nTYPE_INT32\x10\x05\x12\x10\n\x0cTYPE_FIXED64\x10\x06\x12\x10\n\x0cTYPE_FIXED32\x10\x07\x12\r\n\tTYPE_BOOL\x10\x08\x12\x0f\n\x0bTYPE_STRING\x10\t\x12\x0e\n\nTYPE_GROUP\x10\n\x12\x10\n\x0cTYPE_MESSAGE\x10\x0b\x12\x0e\n\nTYPE_BYTES\x10\x0c\x12\x0f\n\x0bTYPE_UINT32\x10\r\x12\r\n\tTYPE_ENUM\x10\x0e\x12\x11\n\rTYPE_SFIXED32\x10\x0f\x12\x11\n\rTYPE_SFIXED64\x10\x10\x12\x0f\n\x0bTYPE_SINT32\x10\x11\x12\x0f\n\x0bTYPE_SINT64\x10\x12"C\n\x05Label\x12\x12\n\x0eLABEL_OPTIONAL\x10\x01\x12\x12\n\x0eLABEL_REQUIRED\x10\x02\x12\x12\n\x0eLABEL_REPEATED\x10\x03J\x04\x08\n\x10\x0b"T\n\x14OneofDescriptorProto\x12\x0c\n\x04name\x18\x01 \x01(\t\x12.\n\x07options\x18\x02 \x01(\x0b\x32\x1d.perfetto.protos.OneofOptions"\x80\x01\n\x13\x45numDescriptorProto\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x38\n\x05value\x18\x02 \x03(\x0b\x32).perfetto.protos.EnumValueDescriptorProto\x12\x15\n\rreserved_name\x18\x05 \x03(\tJ\x04\x08\x03\x10\x04J\x04\x08\x04\x10\x05">\n\x18\x45numValueDescriptorProto\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x0e\n\x06number\x18\x02 \x01(\x05J\x04\x08\x03\x10\x04"!\n\x0cOneofOptions*\t\x08\xe8\x07\x10\x80\x80\x80\x80\x02J\x06\x08\xe7\x07\x10\xe8\x07"P\n\x13\x45xtensionDescriptor\x12\x39\n\rextension_set\x18\x01 \x01(\x0b\x32".perfetto.protos.FileDescriptorSet"\x88\x02\n\x0cInodeFileMap\x12\x17\n\x0f\x62lock_device_id\x18\x01 \x01(\x04\x12\x14\n\x0cmount_points\x18\x02 \x03(\t\x12\x34\n\x07\x65ntries\x18\x03 \x03(\x0b\x32#.perfetto.protos.InodeFileMap.Entry\x1a\x92\x01\n\x05\x45ntry\x12\x14\n\x0cinode_number\x18\x01 \x01(\x04\x12\r\n\x05paths\x18\x02 \x03(\t\x12\x36\n\x04type\x18\x03 \x01(\x0e\x32(.perfetto.protos.InodeFileMap.Entry.Type",\n\x04Type\x12\x0b\n\x07UNKNOWN\x10\x00\x12\x08\n\x04\x46ILE\x10\x01\x12\r\n\tDIRECTORY\x10\x02"M\n\x1f\x41ndroidFsDatareadEndFtraceEvent\x12\r\n\x05\x62ytes\x18\x01 \x01(\x05\x12\x0b\n\x03ino\x18\x02 \x01(\x04\x12\x0e\n\x06offset\x18\x03 \x01(\x03"\x8e\x01\n!AndroidFsDatareadStartFtraceEvent\x12\r\n\x05\x62ytes\x18\x01 \x01(\x05\x12\x0f\n\x07\x63mdline\x18\x02 \x01(\t\x12\x0e\n\x06i_size\x18\x03 \x01(\x03\x12\x0b\n\x03ino\x18\x04 \x01(\x04\x12\x0e\n\x06offset\x18\x05 \x01(\x03\x12\x0f\n\x07pathbuf\x18\x06 \x01(\t\x12\x0b\n\x03pid\x18\x07 \x01(\x05"N\n AndroidFsDatawriteEndFtraceEvent\x12\r\n\x05\x62ytes\x18\x01 \x01(\x05\x12\x0b\n\x03ino\x18\x02 \x01(\x04\x12\x0e\n\x06offset\x18\x03 \x01(\x03"\x8f\x01\n"AndroidFsDatawriteStartFtraceEvent\x12\r\n\x05\x62ytes\x18\x01 \x01(\x05\x12\x0f\n\x07\x63mdline\x18\x02 \x01(\t\x12\x0e\n\x06i_size\x18\x03 \x01(\x03\x12\x0b\n\x03ino\x18\x04 \x01(\x04\x12\x0e\n\x06offset\x18\x05 \x01(\x03\x12\x0f\n\x07pathbuf\x18\x06 \x01(\t\x12\x0b\n\x03pid\x18\x07 \x01(\x05"J\n\x1c\x41ndroidFsFsyncEndFtraceEvent\x12\r\n\x05\x62ytes\x18\x01 \x01(\x05\x12\x0b\n\x03ino\x18\x02 \x01(\x04\x12\x0e\n\x06offset\x18\x03 \x01(\x03"l\n\x1e\x41ndroidFsFsyncStartFtraceEvent\x12\x0f\n\x07\x63mdline\x18\x01 \x01(\t\x12\x0e\n\x06i_size\x18\x02 \x01(\x03\x12\x0b\n\x03ino\x18\x03 \x01(\x04\x12\x0f\n\x07pathbuf\x18\x04 \x01(\t\x12\x0b\n\x03pid\x18\x05 \x01(\x05"\xbd\x01\n\x18\x42\x63lIrqTriggerFtraceEvent\x12\n\n\x02id\x18\x01 \x01(\x05\x12\x10\n\x08throttle\x18\x02 \x01(\x05\x12\x12\n\ncpu0_limit\x18\x03 \x01(\x05\x12\x12\n\ncpu1_limit\x18\x04 \x01(\x05\x12\x12\n\ncpu2_limit\x18\x05 \x01(\x05\x12\x11\n\ttpu_limit\x18\x06 \x01(\x05\x12\x11\n\tgpu_limit\x18\x07 \x01(\x05\x12\x0f\n\x07voltage\x18\x08 \x01(\x05\x12\x10\n\x08\x63\x61pacity\x18\t \x01(\x05"\x95\x01\n\x1c\x42inderTransactionFtraceEvent\x12\x10\n\x08\x64\x65\x62ug_id\x18\x01 \x01(\x05\x12\x13\n\x0btarget_node\x18\x02 \x01(\x05\x12\x0f\n\x07to_proc\x18\x03 \x01(\x05\x12\x11\n\tto_thread\x18\x04 \x01(\x05\x12\r\n\x05reply\x18\x05 \x01(\x05\x12\x0c\n\x04\x63ode\x18\x06 \x01(\r\x12\r\n\x05\x66lags\x18\x07 \x01(\r"8\n$BinderTransactionReceivedFtraceEvent\x12\x10\n\x08\x64\x65\x62ug_id\x18\x01 \x01(\x05"v\n\x1c\x42inderSetPriorityFtraceEvent\x12\x0c\n\x04proc\x18\x01 \x01(\x05\x12\x0e\n\x06thread\x18\x02 \x01(\x05\x12\x10\n\x08old_prio\x18\x03 \x01(\r\x12\x10\n\x08new_prio\x18\x04 \x01(\r\x12\x14\n\x0c\x64\x65sired_prio\x18\x05 \x01(\r"$\n\x15\x42inderLockFtraceEvent\x12\x0b\n\x03tag\x18\x01 \x01(\t"&\n\x17\x42inderLockedFtraceEvent\x12\x0b\n\x03tag\x18\x01 \x01(\t"&\n\x17\x42inderUnlockFtraceEvent\x12\x0b\n\x03tag\x18\x01 \x01(\t"}\n$BinderTransactionAllocBufFtraceEvent\x12\x11\n\tdata_size\x18\x01 \x01(\x04\x12\x10\n\x08\x64\x65\x62ug_id\x18\x02 \x01(\x05\x12\x14\n\x0coffsets_size\x18\x03 \x01(\x04\x12\x1a\n\x12\x65xtra_buffers_size\x18\x04 \x01(\x04"\'\n\x18\x42inderCommandFtraceEvent\x12\x0b\n\x03\x63md\x18\x01 \x01(\r"&\n\x17\x42inderReturnFtraceEvent\x12\x0b\n\x03\x63md\x18\x01 \x01(\r"\x81\x01\n\x17\x42lockRqIssueFtraceEvent\x12\x0b\n\x03\x64\x65v\x18\x01 \x01(\x04\x12\x0e\n\x06sector\x18\x02 \x01(\x04\x12\x11\n\tnr_sector\x18\x03 \x01(\r\x12\r\n\x05\x62ytes\x18\x04 \x01(\r\x12\x0c\n\x04rwbs\x18\x05 \x01(\t\x12\x0c\n\x04\x63omm\x18\x06 \x01(\t\x12\x0b\n\x03\x63md\x18\x07 \x01(\t"j\n\x1c\x42lockBioBackmergeFtraceEvent\x12\x0b\n\x03\x64\x65v\x18\x01 \x01(\x04\x12\x0e\n\x06sector\x18\x02 \x01(\x04\x12\x11\n\tnr_sector\x18\x03 \x01(\r\x12\x0c\n\x04rwbs\x18\x04 \x01(\t\x12\x0c\n\x04\x63omm\x18\x05 \x01(\t"g\n\x19\x42lockBioBounceFtraceEvent\x12\x0b\n\x03\x64\x65v\x18\x01 \x01(\x04\x12\x0e\n\x06sector\x18\x02 \x01(\x04\x12\x11\n\tnr_sector\x18\x03 \x01(\r\x12\x0c\n\x04rwbs\x18\x04 \x01(\t\x12\x0c\n\x04\x63omm\x18\x05 \x01(\t"j\n\x1b\x42lockBioCompleteFtraceEvent\x12\x0b\n\x03\x64\x65v\x18\x01 \x01(\x04\x12\x0e\n\x06sector\x18\x02 \x01(\x04\x12\x11\n\tnr_sector\x18\x03 \x01(\r\x12\r\n\x05\x65rror\x18\x04 \x01(\x05\x12\x0c\n\x04rwbs\x18\x05 \x01(\t"k\n\x1d\x42lockBioFrontmergeFtraceEvent\x12\x0b\n\x03\x64\x65v\x18\x01 \x01(\x04\x12\x0e\n\x06sector\x18\x02 \x01(\x04\x12\x11\n\tnr_sector\x18\x03 \x01(\r\x12\x0c\n\x04rwbs\x18\x04 \x01(\t\x12\x0c\n\x04\x63omm\x18\x05 \x01(\t"f\n\x18\x42lockBioQueueFtraceEvent\x12\x0b\n\x03\x64\x65v\x18\x01 \x01(\x04\x12\x0e\n\x06sector\x18\x02 \x01(\x04\x12\x11\n\tnr_sector\x18\x03 \x01(\r\x12\x0c\n\x04rwbs\x18\x04 \x01(\t\x12\x0c\n\x04\x63omm\x18\x05 \x01(\t"}\n\x18\x42lockBioRemapFtraceEvent\x12\x0b\n\x03\x64\x65v\x18\x01 \x01(\x04\x12\x0e\n\x06sector\x18\x02 \x01(\x04\x12\x11\n\tnr_sector\x18\x03 \x01(\r\x12\x0f\n\x07old_dev\x18\x04 \x01(\x04\x12\x12\n\nold_sector\x18\x05 \x01(\x04\x12\x0c\n\x04rwbs\x18\x06 \x01(\t"H\n\x1b\x42lockDirtyBufferFtraceEvent\x12\x0b\n\x03\x64\x65v\x18\x01 \x01(\x04\x12\x0e\n\x06sector\x18\x02 \x01(\x04\x12\x0c\n\x04size\x18\x03 \x01(\x04"c\n\x15\x42lockGetrqFtraceEvent\x12\x0b\n\x03\x64\x65v\x18\x01 \x01(\x04\x12\x0e\n\x06sector\x18\x02 \x01(\x04\x12\x11\n\tnr_sector\x18\x03 \x01(\r\x12\x0c\n\x04rwbs\x18\x04 \x01(\t\x12\x0c\n\x04\x63omm\x18\x05 \x01(\t"$\n\x14\x42lockPlugFtraceEvent\x12\x0c\n\x04\x63omm\x18\x01 \x01(\t"t\n\x17\x42lockRqAbortFtraceEvent\x12\x0b\n\x03\x64\x65v\x18\x01 \x01(\x04\x12\x0e\n\x06sector\x18\x02 \x01(\x04\x12\x11\n\tnr_sector\x18\x03 \x01(\r\x12\x0e\n\x06\x65rrors\x18\x04 \x01(\x05\x12\x0c\n\x04rwbs\x18\x05 \x01(\t\x12\x0b\n\x03\x63md\x18\x06 \x01(\t"\x86\x01\n\x1a\x42lockRqCompleteFtraceEvent\x12\x0b\n\x03\x64\x65v\x18\x01 \x01(\x04\x12\x0e\n\x06sector\x18\x02 \x01(\x04\x12\x11\n\tnr_sector\x18\x03 \x01(\r\x12\x0e\n\x06\x65rrors\x18\x04 \x01(\x05\x12\x0c\n\x04rwbs\x18\x05 \x01(\t\x12\x0b\n\x03\x63md\x18\x06 \x01(\t\x12\r\n\x05\x65rror\x18\x07 \x01(\x05"\x82\x01\n\x18\x42lockRqInsertFtraceEvent\x12\x0b\n\x03\x64\x65v\x18\x01 \x01(\x04\x12\x0e\n\x06sector\x18\x02 \x01(\x04\x12\x11\n\tnr_sector\x18\x03 \x01(\r\x12\r\n\x05\x62ytes\x18\x04 \x01(\r\x12\x0c\n\x04rwbs\x18\x05 \x01(\t\x12\x0c\n\x04\x63omm\x18\x06 \x01(\t\x12\x0b\n\x03\x63md\x18\x07 \x01(\t"\x8d\x01\n\x17\x42lockRqRemapFtraceEvent\x12\x0b\n\x03\x64\x65v\x18\x01 \x01(\x04\x12\x0e\n\x06sector\x18\x02 \x01(\x04\x12\x11\n\tnr_sector\x18\x03 \x01(\r\x12\x0f\n\x07old_dev\x18\x04 \x01(\x04\x12\x12\n\nold_sector\x18\x05 \x01(\x04\x12\x0f\n\x07nr_bios\x18\x06 \x01(\r\x12\x0c\n\x04rwbs\x18\x07 \x01(\t"v\n\x19\x42lockRqRequeueFtraceEvent\x12\x0b\n\x03\x64\x65v\x18\x01 \x01(\x04\x12\x0e\n\x06sector\x18\x02 \x01(\x04\x12\x11\n\tnr_sector\x18\x03 \x01(\r\x12\x0e\n\x06\x65rrors\x18\x04 \x01(\x05\x12\x0c\n\x04rwbs\x18\x05 \x01(\t\x12\x0b\n\x03\x63md\x18\x06 \x01(\t"e\n\x17\x42lockSleeprqFtraceEvent\x12\x0b\n\x03\x64\x65v\x18\x01 \x01(\x04\x12\x0e\n\x06sector\x18\x02 \x01(\x04\x12\x11\n\tnr_sector\x18\x03 \x01(\r\x12\x0c\n\x04rwbs\x18\x04 \x01(\t\x12\x0c\n\x04\x63omm\x18\x05 \x01(\t"d\n\x15\x42lockSplitFtraceEvent\x12\x0b\n\x03\x64\x65v\x18\x01 \x01(\x04\x12\x0e\n\x06sector\x18\x02 \x01(\x04\x12\x12\n\nnew_sector\x18\x03 \x01(\x04\x12\x0c\n\x04rwbs\x18\x04 \x01(\t\x12\x0c\n\x04\x63omm\x18\x05 \x01(\t"H\n\x1b\x42lockTouchBufferFtraceEvent\x12\x0b\n\x03\x64\x65v\x18\x01 \x01(\x04\x12\x0e\n\x06sector\x18\x02 \x01(\x04\x12\x0c\n\x04size\x18\x03 \x01(\x04"5\n\x16\x42lockUnplugFtraceEvent\x12\r\n\x05nr_rq\x18\x01 \x01(\x05\x12\x0c\n\x04\x63omm\x18\x02 \x01(\t"\x8e\x01\n\x1b\x43groupAttachTaskFtraceEvent\x12\x10\n\x08\x64st_root\x18\x01 \x01(\x05\x12\x0e\n\x06\x64st_id\x18\x02 \x01(\x05\x12\x0b\n\x03pid\x18\x03 \x01(\x05\x12\x0c\n\x04\x63omm\x18\x04 \x01(\t\x12\r\n\x05\x63name\x18\x05 \x01(\t\x12\x11\n\tdst_level\x18\x06 \x01(\x05\x12\x10\n\x08\x64st_path\x18\x07 \x01(\t"^\n\x16\x43groupMkdirFtraceEvent\x12\x0c\n\x04root\x18\x01 \x01(\x05\x12\n\n\x02id\x18\x02 \x01(\x05\x12\r\n\x05\x63name\x18\x03 \x01(\t\x12\r\n\x05level\x18\x04 \x01(\x05\x12\x0c\n\x04path\x18\x05 \x01(\t"G\n\x18\x43groupRemountFtraceEvent\x12\x0c\n\x04root\x18\x01 \x01(\x05\x12\x0f\n\x07ss_mask\x18\x02 \x01(\r\x12\x0c\n\x04name\x18\x03 \x01(\t"^\n\x16\x43groupRmdirFtraceEvent\x12\x0c\n\x04root\x18\x01 \x01(\x05\x12\n\n\x02id\x18\x02 \x01(\x05\x12\r\n\x05\x63name\x18\x03 \x01(\t\x12\r\n\x05level\x18\x04 \x01(\x05\x12\x0c\n\x04path\x18\x05 \x01(\t"\x91\x01\n\x1e\x43groupTransferTasksFtraceEvent\x12\x10\n\x08\x64st_root\x18\x01 \x01(\x05\x12\x0e\n\x06\x64st_id\x18\x02 \x01(\x05\x12\x0b\n\x03pid\x18\x03 \x01(\x05\x12\x0c\n\x04\x63omm\x18\x04 \x01(\t\x12\r\n\x05\x63name\x18\x05 \x01(\t\x12\x11\n\tdst_level\x18\x06 \x01(\x05\x12\x10\n\x08\x64st_path\x18\x07 \x01(\t"K\n\x1c\x43groupDestroyRootFtraceEvent\x12\x0c\n\x04root\x18\x01 \x01(\x05\x12\x0f\n\x07ss_mask\x18\x02 \x01(\r\x12\x0c\n\x04name\x18\x03 \x01(\t"`\n\x18\x43groupReleaseFtraceEvent\x12\x0c\n\x04root\x18\x01 \x01(\x05\x12\n\n\x02id\x18\x02 \x01(\x05\x12\r\n\x05\x63name\x18\x03 \x01(\t\x12\r\n\x05level\x18\x04 \x01(\x05\x12\x0c\n\x04path\x18\x05 \x01(\t"_\n\x17\x43groupRenameFtraceEvent\x12\x0c\n\x04root\x18\x01 \x01(\x05\x12\n\n\x02id\x18\x02 \x01(\x05\x12\r\n\x05\x63name\x18\x03 \x01(\t\x12\r\n\x05level\x18\x04 \x01(\x05\x12\x0c\n\x04path\x18\x05 \x01(\t"I\n\x1a\x43groupSetupRootFtraceEvent\x12\x0c\n\x04root\x18\x01 \x01(\x05\x12\x0f\n\x07ss_mask\x18\x02 \x01(\r\x12\x0c\n\x04name\x18\x03 \x01(\t"$\n\x14\x43lkEnableFtraceEvent\x12\x0c\n\x04name\x18\x01 \x01(\t"%\n\x15\x43lkDisableFtraceEvent\x12\x0c\n\x04name\x18\x01 \x01(\t"3\n\x15\x43lkSetRateFtraceEvent\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x0c\n\x04rate\x18\x02 \x01(\x04"F\n\x18\x43maAllocStartFtraceEvent\x12\r\n\x05\x61lign\x18\x01 \x01(\r\x12\r\n\x05\x63ount\x18\x02 \x01(\r\x12\x0c\n\x04name\x18\x03 \x01(\t"\xc4\x01\n\x17\x43maAllocInfoFtraceEvent\x12\r\n\x05\x61lign\x18\x01 \x01(\r\x12\r\n\x05\x63ount\x18\x02 \x01(\r\x12\x0f\n\x07\x65rr_iso\x18\x03 \x01(\r\x12\x0f\n\x07\x65rr_mig\x18\x04 \x01(\r\x12\x10\n\x08\x65rr_test\x18\x05 \x01(\r\x12\x0c\n\x04name\x18\x06 \x01(\t\x12\x11\n\tnr_mapped\x18\x07 \x01(\x04\x12\x13\n\x0bnr_migrated\x18\x08 \x01(\x04\x12\x14\n\x0cnr_reclaimed\x18\t \x01(\x04\x12\x0b\n\x03pfn\x18\n \x01(\x04"y\n\x1cMmCompactionBeginFtraceEvent\x12\x12\n\nzone_start\x18\x01 \x01(\x04\x12\x13\n\x0bmigrate_pfn\x18\x02 \x01(\x04\x12\x10\n\x08\x66ree_pfn\x18\x03 \x01(\x04\x12\x10\n\x08zone_end\x18\x04 \x01(\x04\x12\x0c\n\x04sync\x18\x05 \x01(\r"\x90\x01\n&MmCompactionDeferCompactionFtraceEvent\x12\x0b\n\x03nid\x18\x01 \x01(\x05\x12\x0b\n\x03idx\x18\x02 \x01(\r\x12\r\n\x05order\x18\x03 \x01(\x05\x12\x12\n\nconsidered\x18\x04 \x01(\r\x12\x13\n\x0b\x64\x65\x66\x65r_shift\x18\x05 \x01(\r\x12\x14\n\x0corder_failed\x18\x06 \x01(\x05"\x89\x01\n\x1fMmCompactionDeferredFtraceEvent\x12\x0b\n\x03nid\x18\x01 \x01(\x05\x12\x0b\n\x03idx\x18\x02 \x01(\r\x12\r\n\x05order\x18\x03 \x01(\x05\x12\x12\n\nconsidered\x18\x04 \x01(\r\x12\x13\n\x0b\x64\x65\x66\x65r_shift\x18\x05 \x01(\r\x12\x14\n\x0corder_failed\x18\x06 \x01(\x05"\x8b\x01\n!MmCompactionDeferResetFtraceEvent\x12\x0b\n\x03nid\x18\x01 \x01(\x05\x12\x0b\n\x03idx\x18\x02 \x01(\r\x12\r\n\x05order\x18\x03 \x01(\x05\x12\x12\n\nconsidered\x18\x04 \x01(\r\x12\x13\n\x0b\x64\x65\x66\x65r_shift\x18\x05 \x01(\r\x12\x14\n\x0corder_failed\x18\x06 \x01(\x05"\x87\x01\n\x1aMmCompactionEndFtraceEvent\x12\x12\n\nzone_start\x18\x01 \x01(\x04\x12\x13\n\x0bmigrate_pfn\x18\x02 \x01(\x04\x12\x10\n\x08\x66ree_pfn\x18\x03 \x01(\x04\x12\x10\n\x08zone_end\x18\x04 \x01(\x04\x12\x0c\n\x04sync\x18\x05 \x01(\r\x12\x0e\n\x06status\x18\x06 \x01(\x05"W\n\x1fMmCompactionFinishedFtraceEvent\x12\x0b\n\x03nid\x18\x01 \x01(\x05\x12\x0b\n\x03idx\x18\x02 \x01(\r\x12\r\n\x05order\x18\x03 \x01(\x05\x12\x0b\n\x03ret\x18\x04 \x01(\x05"s\n\'MmCompactionIsolateFreepagesFtraceEvent\x12\x11\n\tstart_pfn\x18\x01 \x01(\x04\x12\x0f\n\x07\x65nd_pfn\x18\x02 \x01(\x04\x12\x12\n\nnr_scanned\x18\x03 \x01(\x04\x12\x10\n\x08nr_taken\x18\x04 \x01(\x04"v\n*MmCompactionIsolateMigratepagesFtraceEvent\x12\x11\n\tstart_pfn\x18\x01 \x01(\x04\x12\x0f\n\x07\x65nd_pfn\x18\x02 \x01(\x04\x12\x12\n\nnr_scanned\x18\x03 \x01(\x04\x12\x10\n\x08nr_taken\x18\x04 \x01(\x04"4\n%MmCompactionKcompactdSleepFtraceEvent\x12\x0b\n\x03nid\x18\x01 \x01(\x05"r\n$MmCompactionKcompactdWakeFtraceEvent\x12\x0b\n\x03nid\x18\x01 \x01(\x05\x12\r\n\x05order\x18\x02 \x01(\x05\x12\x15\n\rclasszone_idx\x18\x03 \x01(\r\x12\x17\n\x0fhighest_zoneidx\x18\x04 \x01(\r"M\n#MmCompactionMigratepagesFtraceEvent\x12\x13\n\x0bnr_migrated\x18\x01 \x01(\x04\x12\x11\n\tnr_failed\x18\x02 \x01(\x04"W\n\x1fMmCompactionSuitableFtraceEvent\x12\x0b\n\x03nid\x18\x01 \x01(\x05\x12\x0b\n\x03idx\x18\x02 \x01(\r\x12\r\n\x05order\x18\x03 \x01(\x05\x12\x0b\n\x03ret\x18\x04 \x01(\x05"g\n(MmCompactionTryToCompactPagesFtraceEvent\x12\r\n\x05order\x18\x01 \x01(\x05\x12\x10\n\x08gfp_mask\x18\x02 \x01(\r\x12\x0c\n\x04mode\x18\x03 \x01(\r\x12\x0c\n\x04prio\x18\x04 \x01(\x05"t\n&MmCompactionWakeupKcompactdFtraceEvent\x12\x0b\n\x03nid\x18\x01 \x01(\x05\x12\r\n\x05order\x18\x02 \x01(\x05\x12\x15\n\rclasszone_idx\x18\x03 \x01(\r\x12\x17\n\x0fhighest_zoneidx\x18\x04 \x01(\r"L\n\x14\x43puhpExitFtraceEvent\x12\x0b\n\x03\x63pu\x18\x01 \x01(\r\x12\x0b\n\x03idx\x18\x02 \x01(\x05\x12\x0b\n\x03ret\x18\x03 \x01(\x05\x12\r\n\x05state\x18\x04 \x01(\x05"S\n\x1a\x43puhpMultiEnterFtraceEvent\x12\x0b\n\x03\x63pu\x18\x01 \x01(\r\x12\x0b\n\x03\x66un\x18\x02 \x01(\x04\x12\x0b\n\x03idx\x18\x03 \x01(\x05\x12\x0e\n\x06target\x18\x04 \x01(\x05"N\n\x15\x43puhpEnterFtraceEvent\x12\x0b\n\x03\x63pu\x18\x01 \x01(\r\x12\x0b\n\x03\x66un\x18\x02 \x01(\x04\x12\x0b\n\x03idx\x18\x03 \x01(\x05\x12\x0e\n\x06target\x18\x04 \x01(\x05"P\n\x17\x43puhpLatencyFtraceEvent\x12\x0b\n\x03\x63pu\x18\x01 \x01(\r\x12\x0b\n\x03ret\x18\x02 \x01(\x05\x12\r\n\x05state\x18\x03 \x01(\r\x12\x0c\n\x04time\x18\x04 \x01(\x04"W\n\x15\x43puhpPauseFtraceEvent\x12\x13\n\x0b\x61\x63tive_cpus\x18\x01 \x01(\r\x12\x0c\n\x04\x63pus\x18\x02 \x01(\r\x12\r\n\x05pause\x18\x03 \x01(\r\x12\x0c\n\x04time\x18\x04 \x01(\r"\xaa\x01\n\x1e\x43rosEcSensorhubDataFtraceEvent\x12\x14\n\x0c\x63urrent_time\x18\x01 \x01(\x03\x12\x19\n\x11\x63urrent_timestamp\x18\x02 \x01(\x03\x12\r\n\x05\x64\x65lta\x18\x03 \x01(\x03\x12\x19\n\x11\x65\x63_fifo_timestamp\x18\x04 \x01(\r\x12\x15\n\rec_sensor_num\x18\x05 \x01(\r\x12\x16\n\x0e\x66ifo_timestamp\x18\x06 \x01(\x03"1\n\x14\x44\x63vshFreqFtraceEvent\x12\x0b\n\x03\x63pu\x18\x01 \x01(\x04\x12\x0c\n\x04\x66req\x18\x02 \x01(\x04"[\n\x17\x44maFenceInitFtraceEvent\x12\x0f\n\x07\x63ontext\x18\x01 \x01(\r\x12\x0e\n\x06\x64river\x18\x02 \x01(\t\x12\r\n\x05seqno\x18\x03 \x01(\r\x12\x10\n\x08timeline\x18\x04 \x01(\t"[\n\x17\x44maFenceEmitFtraceEvent\x12\x0f\n\x07\x63ontext\x18\x01 \x01(\r\x12\x0e\n\x06\x64river\x18\x02 \x01(\t\x12\r\n\x05seqno\x18\x03 \x01(\r\x12\x10\n\x08timeline\x18\x04 \x01(\t"_\n\x1b\x44maFenceSignaledFtraceEvent\x12\x0f\n\x07\x63ontext\x18\x01 \x01(\r\x12\x0e\n\x06\x64river\x18\x02 \x01(\t\x12\r\n\x05seqno\x18\x03 \x01(\r\x12\x10\n\x08timeline\x18\x04 \x01(\t"`\n\x1c\x44maFenceWaitStartFtraceEvent\x12\x0f\n\x07\x63ontext\x18\x01 \x01(\r\x12\x0e\n\x06\x64river\x18\x02 \x01(\t\x12\r\n\x05seqno\x18\x03 \x01(\r\x12\x10\n\x08timeline\x18\x04 \x01(\t"^\n\x1a\x44maFenceWaitEndFtraceEvent\x12\x0f\n\x07\x63ontext\x18\x01 \x01(\r\x12\x0e\n\x06\x64river\x18\x02 \x01(\t\x12\r\n\x05seqno\x18\x03 \x01(\r\x12\x10\n\x08timeline\x18\x04 \x01(\t"M\n\x16\x44maHeapStatFtraceEvent\x12\r\n\x05inode\x18\x01 \x01(\x04\x12\x0b\n\x03len\x18\x02 \x01(\x03\x12\x17\n\x0ftotal_allocated\x18\x03 \x01(\x04"\x81\x01\n\x1e\x44puTracingMarkWriteFtraceEvent\x12\x0b\n\x03pid\x18\x01 \x01(\x05\x12\x12\n\ntrace_name\x18\x02 \x01(\t\x12\x13\n\x0btrace_begin\x18\x03 \x01(\r\x12\x0c\n\x04name\x18\x04 \x01(\t\x12\x0c\n\x04type\x18\x05 \x01(\r\x12\r\n\x05value\x18\x06 \x01(\x05"A\n\x1e\x44puDsiCmdFifoStatusFtraceEvent\x12\x0e\n\x06header\x18\x01 \x01(\r\x12\x0f\n\x07payload\x18\x02 \x01(\r"2\n\x13\x44puDsiRxFtraceEvent\x12\x0b\n\x03\x63md\x18\x01 \x01(\r\x12\x0e\n\x06rx_buf\x18\x02 \x01(\r"S\n\x13\x44puDsiTxFtraceEvent\x12\x0c\n\x04type\x18\x01 \x01(\r\x12\x0e\n\x06tx_buf\x18\x02 \x01(\r\x12\x0c\n\x04last\x18\x03 \x01(\r\x12\x10\n\x08\x64\x65lay_ms\x18\x04 \x01(\r"W\n\x19\x44rmVblankEventFtraceEvent\x12\x0c\n\x04\x63rtc\x18\x01 \x01(\x05\x12\x11\n\thigh_prec\x18\x02 \x01(\r\x12\x0b\n\x03seq\x18\x03 \x01(\r\x12\x0c\n\x04time\x18\x04 \x01(\x03"M\n"DrmVblankEventDeliveredFtraceEvent\x12\x0c\n\x04\x63rtc\x18\x01 \x01(\x05\x12\x0c\n\x04\x66ile\x18\x02 \x01(\x04\x12\x0b\n\x03seq\x18\x03 \x01(\r"`\n\x1b\x45xt4DaWriteBeginFtraceEvent\x12\x0b\n\x03\x64\x65v\x18\x01 \x01(\x04\x12\x0b\n\x03ino\x18\x02 \x01(\x04\x12\x0b\n\x03pos\x18\x03 \x01(\x03\x12\x0b\n\x03len\x18\x04 \x01(\r\x12\r\n\x05\x66lags\x18\x05 \x01(\r"_\n\x19\x45xt4DaWriteEndFtraceEvent\x12\x0b\n\x03\x64\x65v\x18\x01 \x01(\x04\x12\x0b\n\x03ino\x18\x02 \x01(\x04\x12\x0b\n\x03pos\x18\x03 \x01(\x03\x12\x0b\n\x03len\x18\x04 \x01(\r\x12\x0e\n\x06\x63opied\x18\x05 \x01(\r"Z\n\x1c\x45xt4SyncFileEnterFtraceEvent\x12\x0b\n\x03\x64\x65v\x18\x01 \x01(\x04\x12\x0b\n\x03ino\x18\x02 \x01(\x04\x12\x0e\n\x06parent\x18\x03 \x01(\x04\x12\x10\n\x08\x64\x61tasync\x18\x04 \x01(\x05"D\n\x1b\x45xt4SyncFileExitFtraceEvent\x12\x0b\n\x03\x64\x65v\x18\x01 \x01(\x04\x12\x0b\n\x03ino\x18\x02 \x01(\x04\x12\x0b\n\x03ret\x18\x03 \x01(\x05"b\n\x1c\x45xt4AllocDaBlocksFtraceEvent\x12\x0b\n\x03\x64\x65v\x18\x01 \x01(\x04\x12\x0b\n\x03ino\x18\x02 \x01(\x04\x12\x13\n\x0b\x64\x61ta_blocks\x18\x03 \x01(\r\x12\x13\n\x0bmeta_blocks\x18\x04 \x01(\r"\xc1\x01\n\x1d\x45xt4AllocateBlocksFtraceEvent\x12\x0b\n\x03\x64\x65v\x18\x01 \x01(\x04\x12\x0b\n\x03ino\x18\x02 \x01(\x04\x12\r\n\x05\x62lock\x18\x03 \x01(\x04\x12\x0b\n\x03len\x18\x04 \x01(\r\x12\x0f\n\x07logical\x18\x05 \x01(\r\x12\r\n\x05lleft\x18\x06 \x01(\r\x12\x0e\n\x06lright\x18\x07 \x01(\r\x12\x0c\n\x04goal\x18\x08 \x01(\x04\x12\r\n\x05pleft\x18\t \x01(\x04\x12\x0e\n\x06pright\x18\n \x01(\x04\x12\r\n\x05\x66lags\x18\x0b \x01(\r"S\n\x1c\x45xt4AllocateInodeFtraceEvent\x12\x0b\n\x03\x64\x65v\x18\x01 \x01(\x04\x12\x0b\n\x03ino\x18\x02 \x01(\x04\x12\x0b\n\x03\x64ir\x18\x03 \x01(\x04\x12\x0c\n\x04mode\x18\x04 \x01(\r"Q\n#Ext4BeginOrderedTruncateFtraceEvent\x12\x0b\n\x03\x64\x65v\x18\x01 \x01(\x04\x12\x0b\n\x03ino\x18\x02 \x01(\x04\x12\x10\n\x08new_size\x18\x03 \x01(\x03"U\n\x1c\x45xt4CollapseRangeFtraceEvent\x12\x0b\n\x03\x64\x65v\x18\x01 \x01(\x04\x12\x0b\n\x03ino\x18\x02 \x01(\x04\x12\x0e\n\x06offset\x18\x03 \x01(\x03\x12\x0b\n\x03len\x18\x04 \x01(\x03"\xca\x01\n\x1d\x45xt4DaReleaseSpaceFtraceEvent\x12\x0b\n\x03\x64\x65v\x18\x01 \x01(\x04\x12\x0b\n\x03ino\x18\x02 \x01(\x04\x12\x10\n\x08i_blocks\x18\x03 \x01(\x04\x12\x14\n\x0c\x66reed_blocks\x18\x04 \x01(\x05\x12\x1c\n\x14reserved_data_blocks\x18\x05 \x01(\x05\x12\x1c\n\x14reserved_meta_blocks\x18\x06 \x01(\x05\x12\x1d\n\x15\x61llocated_meta_blocks\x18\x07 \x01(\x05\x12\x0c\n\x04mode\x18\x08 \x01(\r"\xa8\x01\n\x1d\x45xt4DaReserveSpaceFtraceEvent\x12\x0b\n\x03\x64\x65v\x18\x01 \x01(\x04\x12\x0b\n\x03ino\x18\x02 \x01(\x04\x12\x10\n\x08i_blocks\x18\x03 \x01(\x04\x12\x1c\n\x14reserved_data_blocks\x18\x04 \x01(\x05\x12\x1c\n\x14reserved_meta_blocks\x18\x05 \x01(\x05\x12\x0c\n\x04mode\x18\x06 \x01(\r\x12\x11\n\tmd_needed\x18\x07 \x01(\x05"\xe4\x01\n#Ext4DaUpdateReserveSpaceFtraceEvent\x12\x0b\n\x03\x64\x65v\x18\x01 \x01(\x04\x12\x0b\n\x03ino\x18\x02 \x01(\x04\x12\x10\n\x08i_blocks\x18\x03 \x01(\x04\x12\x13\n\x0bused_blocks\x18\x04 \x01(\x05\x12\x1c\n\x14reserved_data_blocks\x18\x05 \x01(\x05\x12\x1c\n\x14reserved_meta_blocks\x18\x06 \x01(\x05\x12\x1d\n\x15\x61llocated_meta_blocks\x18\x07 \x01(\x05\x12\x13\n\x0bquota_claim\x18\x08 \x01(\x05\x12\x0c\n\x04mode\x18\t \x01(\r"\xcf\x01\n\x1b\x45xt4DaWritePagesFtraceEvent\x12\x0b\n\x03\x64\x65v\x18\x01 \x01(\x04\x12\x0b\n\x03ino\x18\x02 \x01(\x04\x12\x12\n\nfirst_page\x18\x03 \x01(\x04\x12\x13\n\x0bnr_to_write\x18\x04 \x01(\x03\x12\x11\n\tsync_mode\x18\x05 \x01(\x05\x12\x11\n\tb_blocknr\x18\x06 \x01(\x04\x12\x0e\n\x06\x62_size\x18\x07 \x01(\r\x12\x0f\n\x07\x62_state\x18\x08 \x01(\r\x12\x0f\n\x07io_done\x18\t \x01(\x05\x12\x15\n\rpages_written\x18\n \x01(\x05"g\n!Ext4DaWritePagesExtentFtraceEvent\x12\x0b\n\x03\x64\x65v\x18\x01 \x01(\x04\x12\x0b\n\x03ino\x18\x02 \x01(\x04\x12\x0c\n\x04lblk\x18\x03 \x01(\x04\x12\x0b\n\x03len\x18\x04 \x01(\r\x12\r\n\x05\x66lags\x18\x05 \x01(\r"^\n\x1c\x45xt4DirectIOEnterFtraceEvent\x12\x0b\n\x03\x64\x65v\x18\x01 \x01(\x04\x12\x0b\n\x03ino\x18\x02 \x01(\x04\x12\x0b\n\x03pos\x18\x03 \x01(\x03\x12\x0b\n\x03len\x18\x04 \x01(\x04\x12\n\n\x02rw\x18\x05 \x01(\x05"j\n\x1b\x45xt4DirectIOExitFtraceEvent\x12\x0b\n\x03\x64\x65v\x18\x01 \x01(\x04\x12\x0b\n\x03ino\x18\x02 \x01(\x04\x12\x0b\n\x03pos\x18\x03 \x01(\x03\x12\x0b\n\x03len\x18\x04 \x01(\x04\x12\n\n\x02rw\x18\x05 \x01(\x05\x12\x0b\n\x03ret\x18\x06 \x01(\x05"G\n\x1c\x45xt4DiscardBlocksFtraceEvent\x12\x0b\n\x03\x64\x65v\x18\x01 \x01(\x04\x12\x0b\n\x03\x62lk\x18\x02 \x01(\x04\x12\r\n\x05\x63ount\x18\x03 \x01(\x04"]\n$Ext4DiscardPreallocationsFtraceEvent\x12\x0b\n\x03\x64\x65v\x18\x01 \x01(\x04\x12\x0b\n\x03ino\x18\x02 \x01(\x04\x12\x0b\n\x03len\x18\x03 \x01(\r\x12\x0e\n\x06needed\x18\x04 \x01(\r"B\n\x18\x45xt4DropInodeFtraceEvent\x12\x0b\n\x03\x64\x65v\x18\x01 \x01(\x04\x12\x0b\n\x03ino\x18\x02 \x01(\x04\x12\x0c\n\x04\x64rop\x18\x03 \x01(\x05"q\n\x1c\x45xt4EsCacheExtentFtraceEvent\x12\x0b\n\x03\x64\x65v\x18\x01 \x01(\x04\x12\x0b\n\x03ino\x18\x02 \x01(\x04\x12\x0c\n\x04lblk\x18\x03 \x01(\r\x12\x0b\n\x03len\x18\x04 \x01(\r\x12\x0c\n\x04pblk\x18\x05 \x01(\x04\x12\x0e\n\x06status\x18\x06 \x01(\r"V\n,Ext4EsFindDelayedExtentRangeEnterFtraceEvent\x12\x0b\n\x03\x64\x65v\x18\x01 \x01(\x04\x12\x0b\n\x03ino\x18\x02 \x01(\x04\x12\x0c\n\x04lblk\x18\x03 \x01(\r"\x80\x01\n+Ext4EsFindDelayedExtentRangeExitFtraceEvent\x12\x0b\n\x03\x64\x65v\x18\x01 \x01(\x04\x12\x0b\n\x03ino\x18\x02 \x01(\x04\x12\x0c\n\x04lblk\x18\x03 \x01(\r\x12\x0b\n\x03len\x18\x04 \x01(\r\x12\x0c\n\x04pblk\x18\x05 \x01(\x04\x12\x0e\n\x06status\x18\x06 \x01(\x04"r\n\x1d\x45xt4EsInsertExtentFtraceEvent\x12\x0b\n\x03\x64\x65v\x18\x01 \x01(\x04\x12\x0b\n\x03ino\x18\x02 \x01(\x04\x12\x0c\n\x04lblk\x18\x03 \x01(\r\x12\x0b\n\x03len\x18\x04 \x01(\r\x12\x0c\n\x04pblk\x18\x05 \x01(\x04\x12\x0e\n\x06status\x18\x06 \x01(\x04"L\n"Ext4EsLookupExtentEnterFtraceEvent\x12\x0b\n\x03\x64\x65v\x18\x01 \x01(\x04\x12\x0b\n\x03ino\x18\x02 \x01(\x04\x12\x0c\n\x04lblk\x18\x03 \x01(\r"\x85\x01\n!Ext4EsLookupExtentExitFtraceEvent\x12\x0b\n\x03\x64\x65v\x18\x01 \x01(\x04\x12\x0b\n\x03ino\x18\x02 \x01(\x04\x12\x0c\n\x04lblk\x18\x03 \x01(\r\x12\x0b\n\x03len\x18\x04 \x01(\r\x12\x0c\n\x04pblk\x18\x05 \x01(\x04\x12\x0e\n\x06status\x18\x06 \x01(\x04\x12\r\n\x05\x66ound\x18\x07 \x01(\x05"T\n\x1d\x45xt4EsRemoveExtentFtraceEvent\x12\x0b\n\x03\x64\x65v\x18\x01 \x01(\x04\x12\x0b\n\x03ino\x18\x02 \x01(\x04\x12\x0c\n\x04lblk\x18\x03 \x01(\x03\x12\x0b\n\x03len\x18\x04 \x01(\x03"q\n\x17\x45xt4EsShrinkFtraceEvent\x12\x0b\n\x03\x64\x65v\x18\x01 \x01(\x04\x12\x11\n\tnr_shrunk\x18\x02 \x01(\x05\x12\x11\n\tscan_time\x18\x03 \x01(\x04\x12\x12\n\nnr_skipped\x18\x04 \x01(\x05\x12\x0f\n\x07retried\x18\x05 \x01(\x05"R\n\x1c\x45xt4EsShrinkCountFtraceEvent\x12\x0b\n\x03\x64\x65v\x18\x01 \x01(\x04\x12\x12\n\nnr_to_scan\x18\x02 \x01(\x05\x12\x11\n\tcache_cnt\x18\x03 \x01(\x05"V\n Ext4EsShrinkScanEnterFtraceEvent\x12\x0b\n\x03\x64\x65v\x18\x01 \x01(\x04\x12\x12\n\nnr_to_scan\x18\x02 \x01(\x05\x12\x11\n\tcache_cnt\x18\x03 \x01(\x05"T\n\x1f\x45xt4EsShrinkScanExitFtraceEvent\x12\x0b\n\x03\x64\x65v\x18\x01 \x01(\x04\x12\x11\n\tnr_shrunk\x18\x02 \x01(\x05\x12\x11\n\tcache_cnt\x18\x03 \x01(\x05"D\n\x19\x45xt4EvictInodeFtraceEvent\x12\x0b\n\x03\x64\x65v\x18\x01 \x01(\x04\x12\x0b\n\x03ino\x18\x02 \x01(\x04\x12\r\n\x05nlink\x18\x03 \x01(\x05"\x95\x01\n+Ext4ExtConvertToInitializedEnterFtraceEvent\x12\x0b\n\x03\x64\x65v\x18\x01 \x01(\x04\x12\x0b\n\x03ino\x18\x02 \x01(\x04\x12\x0e\n\x06m_lblk\x18\x03 \x01(\r\x12\r\n\x05m_len\x18\x04 \x01(\r\x12\x0e\n\x06u_lblk\x18\x05 \x01(\r\x12\r\n\x05u_len\x18\x06 \x01(\r\x12\x0e\n\x06u_pblk\x18\x07 \x01(\x04"\xc7\x01\n.Ext4ExtConvertToInitializedFastpathFtraceEvent\x12\x0b\n\x03\x64\x65v\x18\x01 \x01(\x04\x12\x0b\n\x03ino\x18\x02 \x01(\x04\x12\x0e\n\x06m_lblk\x18\x03 \x01(\r\x12\r\n\x05m_len\x18\x04 \x01(\r\x12\x0e\n\x06u_lblk\x18\x05 \x01(\r\x12\r\n\x05u_len\x18\x06 \x01(\r\x12\x0e\n\x06u_pblk\x18\x07 \x01(\x04\x12\x0e\n\x06i_lblk\x18\x08 \x01(\r\x12\r\n\x05i_len\x18\t \x01(\r\x12\x0e\n\x06i_pblk\x18\n \x01(\x04"\x9f\x01\n(Ext4ExtHandleUnwrittenExtentsFtraceEvent\x12\x0b\n\x03\x64\x65v\x18\x01 \x01(\x04\x12\x0b\n\x03ino\x18\x02 \x01(\x04\x12\r\n\x05\x66lags\x18\x03 \x01(\x05\x12\x0c\n\x04lblk\x18\x04 \x01(\r\x12\x0c\n\x04pblk\x18\x05 \x01(\x04\x12\x0b\n\x03len\x18\x06 \x01(\r\x12\x11\n\tallocated\x18\x07 \x01(\r\x12\x0e\n\x06newblk\x18\x08 \x01(\x04"P\n\x19\x45xt4ExtInCacheFtraceEvent\x12\x0b\n\x03\x64\x65v\x18\x01 \x01(\x04\x12\x0b\n\x03ino\x18\x02 \x01(\x04\x12\x0c\n\x04lblk\x18\x03 \x01(\r\x12\x0b\n\x03ret\x18\x04 \x01(\x05"T\n\x1c\x45xt4ExtLoadExtentFtraceEvent\x12\x0b\n\x03\x64\x65v\x18\x01 \x01(\x04\x12\x0b\n\x03ino\x18\x02 \x01(\x04\x12\x0c\n\x04pblk\x18\x03 \x01(\x04\x12\x0c\n\x04lblk\x18\x04 \x01(\r"f\n Ext4ExtMapBlocksEnterFtraceEvent\x12\x0b\n\x03\x64\x65v\x18\x01 \x01(\x04\x12\x0b\n\x03ino\x18\x02 \x01(\x04\x12\x0c\n\x04lblk\x18\x03 \x01(\r\x12\x0b\n\x03len\x18\x04 \x01(\r\x12\r\n\x05\x66lags\x18\x05 \x01(\r"\x90\x01\n\x1f\x45xt4ExtMapBlocksExitFtraceEvent\x12\x0b\n\x03\x64\x65v\x18\x01 \x01(\x04\x12\x0b\n\x03ino\x18\x02 \x01(\x04\x12\r\n\x05\x66lags\x18\x03 \x01(\r\x12\x0c\n\x04pblk\x18\x04 \x01(\x04\x12\x0c\n\x04lblk\x18\x05 \x01(\r\x12\x0b\n\x03len\x18\x06 \x01(\r\x12\x0e\n\x06mflags\x18\x07 \x01(\r\x12\x0b\n\x03ret\x18\x08 \x01(\x05"b\n\x1c\x45xt4ExtPutInCacheFtraceEvent\x12\x0b\n\x03\x64\x65v\x18\x01 \x01(\x04\x12\x0b\n\x03ino\x18\x02 \x01(\x04\x12\x0c\n\x04lblk\x18\x03 \x01(\r\x12\x0b\n\x03len\x18\x04 \x01(\r\x12\r\n\x05start\x18\x05 \x01(\x04"d\n\x1d\x45xt4ExtRemoveSpaceFtraceEvent\x12\x0b\n\x03\x64\x65v\x18\x01 \x01(\x04\x12\x0b\n\x03ino\x18\x02 \x01(\x04\x12\r\n\x05start\x18\x03 \x01(\r\x12\x0b\n\x03\x65nd\x18\x04 \x01(\r\x12\r\n\x05\x64\x65pth\x18\x05 \x01(\x05"\xc1\x01\n!Ext4ExtRemoveSpaceDoneFtraceEvent\x12\x0b\n\x03\x64\x65v\x18\x01 \x01(\x04\x12\x0b\n\x03ino\x18\x02 \x01(\x04\x12\r\n\x05start\x18\x03 \x01(\r\x12\x0b\n\x03\x65nd\x18\x04 \x01(\r\x12\r\n\x05\x64\x65pth\x18\x05 \x01(\x05\x12\x0f\n\x07partial\x18\x06 \x01(\x03\x12\x12\n\neh_entries\x18\x07 \x01(\r\x12\x0f\n\x07pc_lblk\x18\x08 \x01(\r\x12\x0f\n\x07pc_pclu\x18\t \x01(\x04\x12\x10\n\x08pc_state\x18\n \x01(\x05"A\n\x17\x45xt4ExtRmIdxFtraceEvent\x12\x0b\n\x03\x64\x65v\x18\x01 \x01(\x04\x12\x0b\n\x03ino\x18\x02 \x01(\x04\x12\x0c\n\x04pblk\x18\x03 \x01(\x04"\xba\x01\n\x18\x45xt4ExtRmLeafFtraceEvent\x12\x0b\n\x03\x64\x65v\x18\x01 \x01(\x04\x12\x0b\n\x03ino\x18\x02 \x01(\x04\x12\x0f\n\x07partial\x18\x03 \x01(\x03\x12\r\n\x05start\x18\x04 \x01(\r\x12\x0f\n\x07\x65\x65_lblk\x18\x05 \x01(\r\x12\x0f\n\x07\x65\x65_pblk\x18\x06 \x01(\x04\x12\x0e\n\x06\x65\x65_len\x18\x07 \x01(\x05\x12\x0f\n\x07pc_lblk\x18\x08 \x01(\r\x12\x0f\n\x07pc_pclu\x18\t \x01(\x04\x12\x10\n\x08pc_state\x18\n \x01(\x05"a\n\x1c\x45xt4ExtShowExtentFtraceEvent\x12\x0b\n\x03\x64\x65v\x18\x01 \x01(\x04\x12\x0b\n\x03ino\x18\x02 \x01(\x04\x12\x0c\n\x04pblk\x18\x03 \x01(\x04\x12\x0c\n\x04lblk\x18\x04 \x01(\r\x12\x0b\n\x03len\x18\x05 \x01(\r"q\n\x1d\x45xt4FallocateEnterFtraceEvent\x12\x0b\n\x03\x64\x65v\x18\x01 \x01(\x04\x12\x0b\n\x03ino\x18\x02 \x01(\x04\x12\x0e\n\x06offset\x18\x03 \x01(\x03\x12\x0b\n\x03len\x18\x04 \x01(\x03\x12\x0c\n\x04mode\x18\x05 \x01(\x05\x12\x0b\n\x03pos\x18\x06 \x01(\x03"b\n\x1c\x45xt4FallocateExitFtraceEvent\x12\x0b\n\x03\x64\x65v\x18\x01 \x01(\x04\x12\x0b\n\x03ino\x18\x02 \x01(\x04\x12\x0b\n\x03pos\x18\x03 \x01(\x03\x12\x0e\n\x06\x62locks\x18\x04 \x01(\r\x12\x0b\n\x03ret\x18\x05 \x01(\x05"\x89\x01\n Ext4FindDelallocRangeFtraceEvent\x12\x0b\n\x03\x64\x65v\x18\x01 \x01(\x04\x12\x0b\n\x03ino\x18\x02 \x01(\x04\x12\x0c\n\x04\x66rom\x18\x03 \x01(\r\x12\n\n\x02to\x18\x04 \x01(\r\x12\x0f\n\x07reverse\x18\x05 \x01(\x05\x12\r\n\x05\x66ound\x18\x06 \x01(\x05\x12\x11\n\tfound_blk\x18\x07 \x01(\r"c\n\x15\x45xt4ForgetFtraceEvent\x12\x0b\n\x03\x64\x65v\x18\x01 \x01(\x04\x12\x0b\n\x03ino\x18\x02 \x01(\x04\x12\r\n\x05\x62lock\x18\x03 \x01(\x04\x12\x13\n\x0bis_metadata\x18\x04 \x01(\x05\x12\x0c\n\x04mode\x18\x05 \x01(\r"p\n\x19\x45xt4FreeBlocksFtraceEvent\x12\x0b\n\x03\x64\x65v\x18\x01 \x01(\x04\x12\x0b\n\x03ino\x18\x02 \x01(\x04\x12\r\n\x05\x62lock\x18\x03 \x01(\x04\x12\r\n\x05\x63ount\x18\x04 \x01(\x04\x12\r\n\x05\x66lags\x18\x05 \x01(\x05\x12\x0c\n\x04mode\x18\x06 \x01(\r"l\n\x18\x45xt4FreeInodeFtraceEvent\x12\x0b\n\x03\x64\x65v\x18\x01 \x01(\x04\x12\x0b\n\x03ino\x18\x02 \x01(\x04\x12\x0b\n\x03uid\x18\x03 \x01(\r\x12\x0b\n\x03gid\x18\x04 \x01(\r\x12\x0e\n\x06\x62locks\x18\x05 \x01(\x04\x12\x0c\n\x04mode\x18\x06 \x01(\r"}\n)Ext4GetImpliedClusterAllocExitFtraceEvent\x12\x0b\n\x03\x64\x65v\x18\x01 \x01(\x04\x12\r\n\x05\x66lags\x18\x02 \x01(\r\x12\x0c\n\x04lblk\x18\x03 \x01(\r\x12\x0c\n\x04pblk\x18\x04 \x01(\x04\x12\x0b\n\x03len\x18\x05 \x01(\r\x12\x0b\n\x03ret\x18\x06 \x01(\x05"]\n&Ext4GetReservedClusterAllocFtraceEvent\x12\x0b\n\x03\x64\x65v\x18\x01 \x01(\x04\x12\x0b\n\x03ino\x18\x02 \x01(\x04\x12\x0c\n\x04lblk\x18\x03 \x01(\r\x12\x0b\n\x03len\x18\x04 \x01(\r"f\n Ext4IndMapBlocksEnterFtraceEvent\x12\x0b\n\x03\x64\x65v\x18\x01 \x01(\x04\x12\x0b\n\x03ino\x18\x02 \x01(\x04\x12\x0c\n\x04lblk\x18\x03 \x01(\r\x12\x0b\n\x03len\x18\x04 \x01(\r\x12\r\n\x05\x66lags\x18\x05 \x01(\r"\x90\x01\n\x1f\x45xt4IndMapBlocksExitFtraceEvent\x12\x0b\n\x03\x64\x65v\x18\x01 \x01(\x04\x12\x0b\n\x03ino\x18\x02 \x01(\x04\x12\r\n\x05\x66lags\x18\x03 \x01(\r\x12\x0c\n\x04pblk\x18\x04 \x01(\x04\x12\x0c\n\x04lblk\x18\x05 \x01(\r\x12\x0b\n\x03len\x18\x06 \x01(\r\x12\x0e\n\x06mflags\x18\x07 \x01(\r\x12\x0b\n\x03ret\x18\x08 \x01(\x05"S\n\x1a\x45xt4InsertRangeFtraceEvent\x12\x0b\n\x03\x64\x65v\x18\x01 \x01(\x04\x12\x0b\n\x03ino\x18\x02 \x01(\x04\x12\x0e\n\x06offset\x18\x03 \x01(\x03\x12\x0b\n\x03len\x18\x04 \x01(\x03"h\n\x1d\x45xt4InvalidatepageFtraceEvent\x12\x0b\n\x03\x64\x65v\x18\x01 \x01(\x04\x12\x0b\n\x03ino\x18\x02 \x01(\x04\x12\r\n\x05index\x18\x03 \x01(\x04\x12\x0e\n\x06offset\x18\x04 \x01(\x04\x12\x0e\n\x06length\x18\x05 \x01(\r"\x81\x01\n\x1b\x45xt4JournalStartFtraceEvent\x12\x0b\n\x03\x64\x65v\x18\x01 \x01(\x04\x12\n\n\x02ip\x18\x02 \x01(\x04\x12\x0e\n\x06\x62locks\x18\x03 \x01(\x05\x12\x12\n\nrsv_blocks\x18\x04 \x01(\x05\x12\x0f\n\x07nblocks\x18\x05 \x01(\x05\x12\x14\n\x0crevoke_creds\x18\x06 \x01(\x05"N\n#Ext4JournalStartReservedFtraceEvent\x12\x0b\n\x03\x64\x65v\x18\x01 \x01(\x04\x12\n\n\x02ip\x18\x02 \x01(\x04\x12\x0e\n\x06\x62locks\x18\x03 \x01(\x05"r\n\'Ext4JournalledInvalidatepageFtraceEvent\x12\x0b\n\x03\x64\x65v\x18\x01 \x01(\x04\x12\x0b\n\x03ino\x18\x02 \x01(\x04\x12\r\n\x05index\x18\x03 \x01(\x04\x12\x0e\n\x06offset\x18\x04 \x01(\x04\x12\x0e\n\x06length\x18\x05 \x01(\r"g\n!Ext4JournalledWriteEndFtraceEvent\x12\x0b\n\x03\x64\x65v\x18\x01 \x01(\x04\x12\x0b\n\x03ino\x18\x02 \x01(\x04\x12\x0b\n\x03pos\x18\x03 \x01(\x03\x12\x0b\n\x03len\x18\x04 \x01(\r\x12\x0e\n\x06\x63opied\x18\x05 \x01(\r"4\n\x18\x45xt4LoadInodeFtraceEvent\x12\x0b\n\x03\x64\x65v\x18\x01 \x01(\x04\x12\x0b\n\x03ino\x18\x02 \x01(\x04"<\n\x1e\x45xt4LoadInodeBitmapFtraceEvent\x12\x0b\n\x03\x64\x65v\x18\x01 \x01(\x04\x12\r\n\x05group\x18\x02 \x01(\r"E\n\x1d\x45xt4MarkInodeDirtyFtraceEvent\x12\x0b\n\x03\x64\x65v\x18\x01 \x01(\x04\x12\x0b\n\x03ino\x18\x02 \x01(\x04\x12\n\n\x02ip\x18\x03 \x01(\x04"9\n\x1b\x45xt4MbBitmapLoadFtraceEvent\x12\x0b\n\x03\x64\x65v\x18\x01 \x01(\x04\x12\r\n\x05group\x18\x02 \x01(\r">\n Ext4MbBuddyBitmapLoadFtraceEvent\x12\x0b\n\x03\x64\x65v\x18\x01 \x01(\x04\x12\r\n\x05group\x18\x02 \x01(\r"E\n&Ext4MbDiscardPreallocationsFtraceEvent\x12\x0b\n\x03\x64\x65v\x18\x01 \x01(\x04\x12\x0e\n\x06needed\x18\x02 \x01(\x05"m\n\x1b\x45xt4MbNewGroupPaFtraceEvent\x12\x0b\n\x03\x64\x65v\x18\x01 \x01(\x04\x12\x0b\n\x03ino\x18\x02 \x01(\x04\x12\x11\n\tpa_pstart\x18\x03 \x01(\x04\x12\x11\n\tpa_lstart\x18\x04 \x01(\x04\x12\x0e\n\x06pa_len\x18\x05 \x01(\r"m\n\x1b\x45xt4MbNewInodePaFtraceEvent\x12\x0b\n\x03\x64\x65v\x18\x01 \x01(\x04\x12\x0b\n\x03ino\x18\x02 \x01(\x04\x12\x11\n\tpa_pstart\x18\x03 \x01(\x04\x12\x11\n\tpa_lstart\x18\x04 \x01(\x04\x12\x0e\n\x06pa_len\x18\x05 \x01(\r"Q\n\x1f\x45xt4MbReleaseGroupPaFtraceEvent\x12\x0b\n\x03\x64\x65v\x18\x01 \x01(\x04\x12\x11\n\tpa_pstart\x18\x02 \x01(\x04\x12\x0e\n\x06pa_len\x18\x03 \x01(\r"Y\n\x1f\x45xt4MbReleaseInodePaFtraceEvent\x12\x0b\n\x03\x64\x65v\x18\x01 \x01(\x04\x12\x0b\n\x03ino\x18\x02 \x01(\x04\x12\r\n\x05\x62lock\x18\x03 \x01(\x04\x12\r\n\x05\x63ount\x18\x04 \x01(\r"\x86\x03\n\x1b\x45xt4MballocAllocFtraceEvent\x12\x0b\n\x03\x64\x65v\x18\x01 \x01(\x04\x12\x0b\n\x03ino\x18\x02 \x01(\x04\x12\x14\n\x0corig_logical\x18\x03 \x01(\r\x12\x12\n\norig_start\x18\x04 \x01(\x05\x12\x12\n\norig_group\x18\x05 \x01(\r\x12\x10\n\x08orig_len\x18\x06 \x01(\x05\x12\x14\n\x0cgoal_logical\x18\x07 \x01(\r\x12\x12\n\ngoal_start\x18\x08 \x01(\x05\x12\x12\n\ngoal_group\x18\t \x01(\r\x12\x10\n\x08goal_len\x18\n \x01(\x05\x12\x16\n\x0eresult_logical\x18\x0b \x01(\r\x12\x14\n\x0cresult_start\x18\x0c \x01(\x05\x12\x14\n\x0cresult_group\x18\r \x01(\r\x12\x12\n\nresult_len\x18\x0e \x01(\x05\x12\r\n\x05\x66ound\x18\x0f \x01(\r\x12\x0e\n\x06groups\x18\x10 \x01(\r\x12\r\n\x05\x62uddy\x18\x11 \x01(\r\x12\r\n\x05\x66lags\x18\x12 \x01(\r\x12\x0c\n\x04tail\x18\x13 \x01(\r\x12\n\n\x02\x63r\x18\x14 \x01(\r"y\n\x1d\x45xt4MballocDiscardFtraceEvent\x12\x0b\n\x03\x64\x65v\x18\x01 \x01(\x04\x12\x0b\n\x03ino\x18\x02 \x01(\x04\x12\x14\n\x0cresult_start\x18\x03 \x01(\x05\x12\x14\n\x0cresult_group\x18\x04 \x01(\r\x12\x12\n\nresult_len\x18\x05 \x01(\x05"v\n\x1a\x45xt4MballocFreeFtraceEvent\x12\x0b\n\x03\x64\x65v\x18\x01 \x01(\x04\x12\x0b\n\x03ino\x18\x02 \x01(\x04\x12\x14\n\x0cresult_start\x18\x03 \x01(\x05\x12\x14\n\x0cresult_group\x18\x04 \x01(\r\x12\x12\n\nresult_len\x18\x05 \x01(\x05"\xe2\x01\n\x1e\x45xt4MballocPreallocFtraceEvent\x12\x0b\n\x03\x64\x65v\x18\x01 \x01(\x04\x12\x0b\n\x03ino\x18\x02 \x01(\x04\x12\x14\n\x0corig_logical\x18\x03 \x01(\r\x12\x12\n\norig_start\x18\x04 \x01(\x05\x12\x12\n\norig_group\x18\x05 \x01(\r\x12\x10\n\x08orig_len\x18\x06 \x01(\x05\x12\x16\n\x0eresult_logical\x18\x07 \x01(\r\x12\x14\n\x0cresult_start\x18\x08 \x01(\x05\x12\x14\n\x0cresult_group\x18\t \x01(\r\x12\x12\n\nresult_len\x18\n \x01(\x05"y\n#Ext4OtherInodeUpdateTimeFtraceEvent\x12\x0b\n\x03\x64\x65v\x18\x01 \x01(\x04\x12\x0b\n\x03ino\x18\x02 \x01(\x04\x12\x10\n\x08orig_ino\x18\x03 \x01(\x04\x12\x0b\n\x03uid\x18\x04 \x01(\r\x12\x0b\n\x03gid\x18\x05 \x01(\r\x12\x0c\n\x04mode\x18\x06 \x01(\r"_\n\x18\x45xt4PunchHoleFtraceEvent\x12\x0b\n\x03\x64\x65v\x18\x01 \x01(\x04\x12\x0b\n\x03ino\x18\x02 \x01(\x04\x12\x0e\n\x06offset\x18\x03 \x01(\x03\x12\x0b\n\x03len\x18\x04 \x01(\x03\x12\x0c\n\x04mode\x18\x05 \x01(\x05"R\n"Ext4ReadBlockBitmapLoadFtraceEvent\x12\x0b\n\x03\x64\x65v\x18\x01 \x01(\x04\x12\r\n\x05group\x18\x02 \x01(\r\x12\x10\n\x08prefetch\x18\x03 \x01(\r"B\n\x17\x45xt4ReadpageFtraceEvent\x12\x0b\n\x03\x64\x65v\x18\x01 \x01(\x04\x12\x0b\n\x03ino\x18\x02 \x01(\x04\x12\r\n\x05index\x18\x03 \x01(\x04"E\n\x1a\x45xt4ReleasepageFtraceEvent\x12\x0b\n\x03\x64\x65v\x18\x01 \x01(\x04\x12\x0b\n\x03ino\x18\x02 \x01(\x04\x12\r\n\x05index\x18\x03 \x01(\x04"\xc8\x01\n\x1b\x45xt4RemoveBlocksFtraceEvent\x12\x0b\n\x03\x64\x65v\x18\x01 \x01(\x04\x12\x0b\n\x03ino\x18\x02 \x01(\x04\x12\x0c\n\x04\x66rom\x18\x03 \x01(\r\x12\n\n\x02to\x18\x04 \x01(\r\x12\x0f\n\x07partial\x18\x05 \x01(\x03\x12\x0f\n\x07\x65\x65_pblk\x18\x06 \x01(\x04\x12\x0f\n\x07\x65\x65_lblk\x18\x07 \x01(\r\x12\x0e\n\x06\x65\x65_len\x18\x08 \x01(\r\x12\x0f\n\x07pc_lblk\x18\t \x01(\r\x12\x0f\n\x07pc_pclu\x18\n \x01(\x04\x12\x10\n\x08pc_state\x18\x0b \x01(\x05"\xb1\x01\n\x1c\x45xt4RequestBlocksFtraceEvent\x12\x0b\n\x03\x64\x65v\x18\x01 \x01(\x04\x12\x0b\n\x03ino\x18\x02 \x01(\x04\x12\x0b\n\x03len\x18\x03 \x01(\r\x12\x0f\n\x07logical\x18\x04 \x01(\r\x12\r\n\x05lleft\x18\x05 \x01(\r\x12\x0e\n\x06lright\x18\x06 \x01(\r\x12\x0c\n\x04goal\x18\x07 \x01(\x04\x12\r\n\x05pleft\x18\x08 \x01(\x04\x12\x0e\n\x06pright\x18\t \x01(\x04\x12\r\n\x05\x66lags\x18\n \x01(\r"E\n\x1b\x45xt4RequestInodeFtraceEvent\x12\x0b\n\x03\x64\x65v\x18\x01 \x01(\x04\x12\x0b\n\x03\x64ir\x18\x02 \x01(\x04\x12\x0c\n\x04mode\x18\x03 \x01(\r"2\n\x15\x45xt4SyncFsFtraceEvent\x12\x0b\n\x03\x64\x65v\x18\x01 \x01(\x04\x12\x0c\n\x04wait\x18\x02 \x01(\x05"m\n\x1a\x45xt4TrimAllFreeFtraceEvent\x12\x11\n\tdev_major\x18\x01 \x01(\x05\x12\x11\n\tdev_minor\x18\x02 \x01(\x05\x12\r\n\x05group\x18\x03 \x01(\r\x12\r\n\x05start\x18\x04 \x01(\x05\x12\x0b\n\x03len\x18\x05 \x01(\x05"l\n\x19\x45xt4TrimExtentFtraceEvent\x12\x11\n\tdev_major\x18\x01 \x01(\x05\x12\x11\n\tdev_minor\x18\x02 \x01(\x05\x12\r\n\x05group\x18\x03 \x01(\r\x12\r\n\x05start\x18\x04 \x01(\x05\x12\x0b\n\x03len\x18\x05 \x01(\x05"H\n\x1c\x45xt4TruncateEnterFtraceEvent\x12\x0b\n\x03\x64\x65v\x18\x01 \x01(\x04\x12\x0b\n\x03ino\x18\x02 \x01(\x04\x12\x0e\n\x06\x62locks\x18\x03 \x01(\x04"G\n\x1b\x45xt4TruncateExitFtraceEvent\x12\x0b\n\x03\x64\x65v\x18\x01 \x01(\x04\x12\x0b\n\x03ino\x18\x02 \x01(\x04\x12\x0e\n\x06\x62locks\x18\x03 \x01(\x04"T\n\x1a\x45xt4UnlinkEnterFtraceEvent\x12\x0b\n\x03\x64\x65v\x18\x01 \x01(\x04\x12\x0b\n\x03ino\x18\x02 \x01(\x04\x12\x0e\n\x06parent\x18\x03 \x01(\x04\x12\x0c\n\x04size\x18\x04 \x01(\x03"B\n\x19\x45xt4UnlinkExitFtraceEvent\x12\x0b\n\x03\x64\x65v\x18\x01 \x01(\x04\x12\x0b\n\x03ino\x18\x02 \x01(\x04\x12\x0b\n\x03ret\x18\x03 \x01(\x05"^\n\x19\x45xt4WriteBeginFtraceEvent\x12\x0b\n\x03\x64\x65v\x18\x01 \x01(\x04\x12\x0b\n\x03ino\x18\x02 \x01(\x04\x12\x0b\n\x03pos\x18\x03 \x01(\x03\x12\x0b\n\x03len\x18\x04 \x01(\r\x12\r\n\x05\x66lags\x18\x05 \x01(\r"]\n\x17\x45xt4WriteEndFtraceEvent\x12\x0b\n\x03\x64\x65v\x18\x01 \x01(\x04\x12\x0b\n\x03ino\x18\x02 \x01(\x04\x12\x0b\n\x03pos\x18\x03 \x01(\x03\x12\x0b\n\x03len\x18\x04 \x01(\r\x12\x0e\n\x06\x63opied\x18\x05 \x01(\r"C\n\x18\x45xt4WritepageFtraceEvent\x12\x0b\n\x03\x64\x65v\x18\x01 \x01(\x04\x12\x0b\n\x03ino\x18\x02 \x01(\x04\x12\r\n\x05index\x18\x03 \x01(\x04"\xe0\x01\n\x19\x45xt4WritepagesFtraceEvent\x12\x0b\n\x03\x64\x65v\x18\x01 \x01(\x04\x12\x0b\n\x03ino\x18\x02 \x01(\x04\x12\x13\n\x0bnr_to_write\x18\x03 \x01(\x03\x12\x15\n\rpages_skipped\x18\x04 \x01(\x03\x12\x13\n\x0brange_start\x18\x05 \x01(\x03\x12\x11\n\trange_end\x18\x06 \x01(\x03\x12\x17\n\x0fwriteback_index\x18\x07 \x01(\x04\x12\x11\n\tsync_mode\x18\x08 \x01(\x05\x12\x13\n\x0b\x66or_kupdate\x18\t \x01(\r\x12\x14\n\x0crange_cyclic\x18\n \x01(\r"\xa2\x01\n\x1f\x45xt4WritepagesResultFtraceEvent\x12\x0b\n\x03\x64\x65v\x18\x01 \x01(\x04\x12\x0b\n\x03ino\x18\x02 \x01(\x04\x12\x0b\n\x03ret\x18\x03 \x01(\x05\x12\x15\n\rpages_written\x18\x04 \x01(\x05\x12\x15\n\rpages_skipped\x18\x05 \x01(\x03\x12\x17\n\x0fwriteback_index\x18\x06 \x01(\x04\x12\x11\n\tsync_mode\x18\x07 \x01(\x05"_\n\x18\x45xt4ZeroRangeFtraceEvent\x12\x0b\n\x03\x64\x65v\x18\x01 \x01(\x04\x12\x0b\n\x03ino\x18\x02 \x01(\x04\x12\x0e\n\x06offset\x18\x03 \x01(\x03\x12\x0b\n\x03len\x18\x04 \x01(\x03\x12\x0c\n\x04mode\x18\x05 \x01(\x05"d\n\x1a\x46\x32\x66sDoSubmitBioFtraceEvent\x12\x0b\n\x03\x64\x65v\x18\x01 \x01(\x04\x12\r\n\x05\x62type\x18\x02 \x01(\x05\x12\x0c\n\x04sync\x18\x03 \x01(\r\x12\x0e\n\x06sector\x18\x04 \x01(\x04\x12\x0c\n\x04size\x18\x05 \x01(\r"\x8e\x01\n\x19\x46\x32\x66sEvictInodeFtraceEvent\x12\x0b\n\x03\x64\x65v\x18\x01 \x01(\x04\x12\x0b\n\x03ino\x18\x02 \x01(\x04\x12\x0c\n\x04pino\x18\x03 \x01(\x04\x12\x0c\n\x04mode\x18\x04 \x01(\r\x12\x0c\n\x04size\x18\x05 \x01(\x03\x12\r\n\x05nlink\x18\x06 \x01(\r\x12\x0e\n\x06\x62locks\x18\x07 \x01(\x04\x12\x0e\n\x06\x61\x64vise\x18\x08 \x01(\r"\x8a\x01\n\x18\x46\x32\x66sFallocateFtraceEvent\x12\x0b\n\x03\x64\x65v\x18\x01 \x01(\x04\x12\x0b\n\x03ino\x18\x02 \x01(\x04\x12\x0c\n\x04mode\x18\x03 \x01(\x05\x12\x0e\n\x06offset\x18\x04 \x01(\x03\x12\x0b\n\x03len\x18\x05 \x01(\x03\x12\x0c\n\x04size\x18\x06 \x01(\x03\x12\x0e\n\x06\x62locks\x18\x07 \x01(\x04\x12\x0b\n\x03ret\x18\x08 \x01(\x05"w\n\x1b\x46\x32\x66sGetDataBlockFtraceEvent\x12\x0b\n\x03\x64\x65v\x18\x01 \x01(\x04\x12\x0b\n\x03ino\x18\x02 \x01(\x04\x12\x0e\n\x06iblock\x18\x03 \x01(\x04\x12\x10\n\x08\x62h_start\x18\x04 \x01(\x04\x12\x0f\n\x07\x62h_size\x18\x05 \x01(\x04\x12\x0b\n\x03ret\x18\x06 \x01(\x05"\xce\x01\n\x18\x46\x32\x66sGetVictimFtraceEvent\x12\x0b\n\x03\x64\x65v\x18\x01 \x01(\x04\x12\x0c\n\x04type\x18\x02 \x01(\x05\x12\x0f\n\x07gc_type\x18\x03 \x01(\x05\x12\x12\n\nalloc_mode\x18\x04 \x01(\x05\x12\x0f\n\x07gc_mode\x18\x05 \x01(\x05\x12\x0e\n\x06victim\x18\x06 \x01(\r\x12\x10\n\x08ofs_unit\x18\x07 \x01(\r\x12\x12\n\npre_victim\x18\x08 \x01(\r\x12\x0f\n\x07prefree\x18\t \x01(\r\x12\x0c\n\x04\x66ree\x18\n \x01(\r\x12\x0c\n\x04\x63ost\x18\x0b \x01(\r"\x88\x01\n\x13\x46\x32\x66sIgetFtraceEvent\x12\x0b\n\x03\x64\x65v\x18\x01 \x01(\x04\x12\x0b\n\x03ino\x18\x02 \x01(\x04\x12\x0c\n\x04pino\x18\x03 \x01(\x04\x12\x0c\n\x04mode\x18\x04 \x01(\r\x12\x0c\n\x04size\x18\x05 \x01(\x03\x12\r\n\x05nlink\x18\x06 \x01(\r\x12\x0e\n\x06\x62locks\x18\x07 \x01(\x04\x12\x0e\n\x06\x61\x64vise\x18\x08 \x01(\r"@\n\x17\x46\x32\x66sIgetExitFtraceEvent\x12\x0b\n\x03\x64\x65v\x18\x01 \x01(\x04\x12\x0b\n\x03ino\x18\x02 \x01(\x04\x12\x0b\n\x03ret\x18\x03 \x01(\x05"@\n\x17\x46\x32\x66sNewInodeFtraceEvent\x12\x0b\n\x03\x64\x65v\x18\x01 \x01(\x04\x12\x0b\n\x03ino\x18\x02 \x01(\x04\x12\x0b\n\x03ret\x18\x03 \x01(\x05"\x8f\x01\n\x17\x46\x32\x66sReadpageFtraceEvent\x12\x0b\n\x03\x64\x65v\x18\x01 \x01(\x04\x12\x0b\n\x03ino\x18\x02 \x01(\x04\x12\r\n\x05index\x18\x03 \x01(\x04\x12\x0f\n\x07\x62lkaddr\x18\x04 \x01(\x04\x12\x0c\n\x04type\x18\x05 \x01(\x05\x12\x0b\n\x03\x64ir\x18\x06 \x01(\x05\x12\r\n\x05\x64irty\x18\x07 \x01(\x05\x12\x10\n\x08uptodate\x18\x08 \x01(\x05"O\n\x1e\x46\x32\x66sReserveNewBlockFtraceEvent\x12\x0b\n\x03\x64\x65v\x18\x01 \x01(\x04\x12\x0b\n\x03nid\x18\x02 \x01(\r\x12\x13\n\x0bofs_in_node\x18\x03 \x01(\r"\x82\x01\n\x1b\x46\x32\x66sSetPageDirtyFtraceEvent\x12\x0b\n\x03\x64\x65v\x18\x01 \x01(\x04\x12\x0b\n\x03ino\x18\x02 \x01(\x04\x12\x0c\n\x04type\x18\x03 \x01(\x05\x12\x0b\n\x03\x64ir\x18\x04 \x01(\x05\x12\r\n\x05index\x18\x05 \x01(\x04\x12\r\n\x05\x64irty\x18\x06 \x01(\x05\x12\x10\n\x08uptodate\x18\x07 \x01(\x05"f\n\x1e\x46\x32\x66sSubmitWritePageFtraceEvent\x12\x0b\n\x03\x64\x65v\x18\x01 \x01(\x04\x12\x0b\n\x03ino\x18\x02 \x01(\x04\x12\x0c\n\x04type\x18\x03 \x01(\x05\x12\r\n\x05index\x18\x04 \x01(\x04\x12\r\n\x05\x62lock\x18\x05 \x01(\r"\x91\x01\n\x1c\x46\x32\x66sSyncFileEnterFtraceEvent\x12\x0b\n\x03\x64\x65v\x18\x01 \x01(\x04\x12\x0b\n\x03ino\x18\x02 \x01(\x04\x12\x0c\n\x04pino\x18\x03 \x01(\x04\x12\x0c\n\x04mode\x18\x04 \x01(\r\x12\x0c\n\x04size\x18\x05 \x01(\x03\x12\r\n\x05nlink\x18\x06 \x01(\r\x12\x0e\n\x06\x62locks\x18\x07 \x01(\x04\x12\x0e\n\x06\x61\x64vise\x18\x08 \x01(\r"z\n\x1b\x46\x32\x66sSyncFileExitFtraceEvent\x12\x0b\n\x03\x64\x65v\x18\x01 \x01(\x04\x12\x0b\n\x03ino\x18\x02 \x01(\x04\x12\x0f\n\x07need_cp\x18\x03 \x01(\r\x12\x10\n\x08\x64\x61tasync\x18\x04 \x01(\x05\x12\x0b\n\x03ret\x18\x05 \x01(\x05\x12\x11\n\tcp_reason\x18\x06 \x01(\x05"A\n\x15\x46\x32\x66sSyncFsFtraceEvent\x12\x0b\n\x03\x64\x65v\x18\x01 \x01(\x04\x12\r\n\x05\x64irty\x18\x02 \x01(\x05\x12\x0c\n\x04wait\x18\x03 \x01(\x05"\x8c\x01\n\x17\x46\x32\x66sTruncateFtraceEvent\x12\x0b\n\x03\x64\x65v\x18\x01 \x01(\x04\x12\x0b\n\x03ino\x18\x02 \x01(\x04\x12\x0c\n\x04pino\x18\x03 \x01(\x04\x12\x0c\n\x04mode\x18\x04 \x01(\r\x12\x0c\n\x04size\x18\x05 \x01(\x03\x12\r\n\x05nlink\x18\x06 \x01(\r\x12\x0e\n\x06\x62locks\x18\x07 \x01(\x04\x12\x0e\n\x06\x61\x64vise\x18\x08 \x01(\r"j\n"F2fsTruncateBlocksEnterFtraceEvent\x12\x0b\n\x03\x64\x65v\x18\x01 \x01(\x04\x12\x0b\n\x03ino\x18\x02 \x01(\x04\x12\x0c\n\x04size\x18\x03 \x01(\x03\x12\x0e\n\x06\x62locks\x18\x04 \x01(\x04\x12\x0c\n\x04\x66rom\x18\x05 \x01(\x04"J\n!F2fsTruncateBlocksExitFtraceEvent\x12\x0b\n\x03\x64\x65v\x18\x01 \x01(\x04\x12\x0b\n\x03ino\x18\x02 \x01(\x04\x12\x0b\n\x03ret\x18\x03 \x01(\x05"j\n&F2fsTruncateDataBlocksRangeFtraceEvent\x12\x0b\n\x03\x64\x65v\x18\x01 \x01(\x04\x12\x0b\n\x03ino\x18\x02 \x01(\x04\x12\x0b\n\x03nid\x18\x03 \x01(\r\x12\x0b\n\x03ofs\x18\x04 \x01(\r\x12\x0c\n\x04\x66ree\x18\x05 \x01(\x05"o\n\'F2fsTruncateInodeBlocksEnterFtraceEvent\x12\x0b\n\x03\x64\x65v\x18\x01 \x01(\x04\x12\x0b\n\x03ino\x18\x02 \x01(\x04\x12\x0c\n\x04size\x18\x03 \x01(\x03\x12\x0e\n\x06\x62locks\x18\x04 \x01(\x04\x12\x0c\n\x04\x66rom\x18\x05 \x01(\x04"O\n&F2fsTruncateInodeBlocksExitFtraceEvent\x12\x0b\n\x03\x64\x65v\x18\x01 \x01(\x04\x12\x0b\n\x03ino\x18\x02 \x01(\x04\x12\x0b\n\x03ret\x18\x03 \x01(\x05"V\n\x1b\x46\x32\x66sTruncateNodeFtraceEvent\x12\x0b\n\x03\x64\x65v\x18\x01 \x01(\x04\x12\x0b\n\x03ino\x18\x02 \x01(\x04\x12\x0b\n\x03nid\x18\x03 \x01(\r\x12\x10\n\x08\x62lk_addr\x18\x04 \x01(\r"\\\n!F2fsTruncateNodesEnterFtraceEvent\x12\x0b\n\x03\x64\x65v\x18\x01 \x01(\x04\x12\x0b\n\x03ino\x18\x02 \x01(\x04\x12\x0b\n\x03nid\x18\x03 \x01(\r\x12\x10\n\x08\x62lk_addr\x18\x04 \x01(\r"I\n F2fsTruncateNodesExitFtraceEvent\x12\x0b\n\x03\x64\x65v\x18\x01 \x01(\x04\x12\x0b\n\x03ino\x18\x02 \x01(\x04\x12\x0b\n\x03ret\x18\x03 \x01(\x05"h\n#F2fsTruncatePartialNodesFtraceEvent\x12\x0b\n\x03\x64\x65v\x18\x01 \x01(\x04\x12\x0b\n\x03ino\x18\x02 \x01(\x04\x12\x0b\n\x03nid\x18\x03 \x01(\r\x12\r\n\x05\x64\x65pth\x18\x04 \x01(\x05\x12\x0b\n\x03\x65rr\x18\x05 \x01(\x05"b\n\x1a\x46\x32\x66sUnlinkEnterFtraceEvent\x12\x0b\n\x03\x64\x65v\x18\x01 \x01(\x04\x12\x0b\n\x03ino\x18\x02 \x01(\x04\x12\x0c\n\x04size\x18\x03 \x01(\x03\x12\x0e\n\x06\x62locks\x18\x04 \x01(\x04\x12\x0c\n\x04name\x18\x05 \x01(\t"B\n\x19\x46\x32\x66sUnlinkExitFtraceEvent\x12\x0b\n\x03\x64\x65v\x18\x01 \x01(\x04\x12\x0b\n\x03ino\x18\x02 \x01(\x04\x12\x0b\n\x03ret\x18\x03 \x01(\x05"\x83\x01\n\x1c\x46\x32\x66sVmPageMkwriteFtraceEvent\x12\x0b\n\x03\x64\x65v\x18\x01 \x01(\x04\x12\x0b\n\x03ino\x18\x02 \x01(\x04\x12\x0c\n\x04type\x18\x03 \x01(\x05\x12\x0b\n\x03\x64ir\x18\x04 \x01(\x05\x12\r\n\x05index\x18\x05 \x01(\x04\x12\r\n\x05\x64irty\x18\x06 \x01(\x05\x12\x10\n\x08uptodate\x18\x07 \x01(\x05"^\n\x19\x46\x32\x66sWriteBeginFtraceEvent\x12\x0b\n\x03\x64\x65v\x18\x01 \x01(\x04\x12\x0b\n\x03ino\x18\x02 \x01(\x04\x12\x0b\n\x03pos\x18\x03 \x01(\x03\x12\x0b\n\x03len\x18\x04 \x01(\r\x12\r\n\x05\x66lags\x18\x05 \x01(\r"]\n\x1e\x46\x32\x66sWriteCheckpointFtraceEvent\x12\x0b\n\x03\x64\x65v\x18\x01 \x01(\x04\x12\x11\n\tis_umount\x18\x02 \x01(\r\x12\x0b\n\x03msg\x18\x03 \x01(\t\x12\x0e\n\x06reason\x18\x04 \x01(\x05"]\n\x17\x46\x32\x66sWriteEndFtraceEvent\x12\x0b\n\x03\x64\x65v\x18\x01 \x01(\x04\x12\x0b\n\x03ino\x18\x02 \x01(\x04\x12\x0b\n\x03pos\x18\x03 \x01(\x03\x12\x0b\n\x03len\x18\x04 \x01(\r\x12\x0e\n\x06\x63opied\x18\x05 \x01(\r"\xa9\x03\n\x15\x46\x32\x66sIostatFtraceEvent\x12\x0f\n\x07\x61pp_bio\x18\x01 \x01(\x04\x12\x10\n\x08\x61pp_brio\x18\x02 \x01(\x04\x12\x0f\n\x07\x61pp_dio\x18\x03 \x01(\x04\x12\x10\n\x08\x61pp_drio\x18\x04 \x01(\x04\x12\x0f\n\x07\x61pp_mio\x18\x05 \x01(\x04\x12\x10\n\x08\x61pp_mrio\x18\x06 \x01(\x04\x12\x0f\n\x07\x61pp_rio\x18\x07 \x01(\x04\x12\x0f\n\x07\x61pp_wio\x18\x08 \x01(\x04\x12\x0b\n\x03\x64\x65v\x18\t \x01(\x04\x12\x10\n\x08\x66s_cdrio\x18\n \x01(\x04\x12\x11\n\tfs_cp_dio\x18\x0b \x01(\x04\x12\x11\n\tfs_cp_mio\x18\x0c \x01(\x04\x12\x11\n\tfs_cp_nio\x18\r \x01(\x04\x12\x0e\n\x06\x66s_dio\x18\x0e \x01(\x04\x12\x12\n\nfs_discard\x18\x0f \x01(\x04\x12\x0f\n\x07\x66s_drio\x18\x10 \x01(\x04\x12\x11\n\tfs_gc_dio\x18\x11 \x01(\x04\x12\x11\n\tfs_gc_nio\x18\x12 \x01(\x04\x12\x10\n\x08\x66s_gdrio\x18\x13 \x01(\x04\x12\x0e\n\x06\x66s_mio\x18\x14 \x01(\x04\x12\x0f\n\x07\x66s_mrio\x18\x15 \x01(\x04\x12\x0e\n\x06\x66s_nio\x18\x16 \x01(\x04\x12\x0f\n\x07\x66s_nrio\x18\x17 \x01(\x04"\xc7\x04\n\x1c\x46\x32\x66sIostatLatencyFtraceEvent\x12\x10\n\x08\x64_rd_avg\x18\x01 \x01(\r\x12\x10\n\x08\x64_rd_cnt\x18\x02 \x01(\r\x12\x11\n\td_rd_peak\x18\x03 \x01(\r\x12\x13\n\x0b\x64_wr_as_avg\x18\x04 \x01(\r\x12\x13\n\x0b\x64_wr_as_cnt\x18\x05 \x01(\r\x12\x14\n\x0c\x64_wr_as_peak\x18\x06 \x01(\r\x12\x12\n\nd_wr_s_avg\x18\x07 \x01(\r\x12\x12\n\nd_wr_s_cnt\x18\x08 \x01(\r\x12\x13\n\x0b\x64_wr_s_peak\x18\t \x01(\r\x12\x0b\n\x03\x64\x65v\x18\n \x01(\x04\x12\x10\n\x08m_rd_avg\x18\x0b \x01(\r\x12\x10\n\x08m_rd_cnt\x18\x0c \x01(\r\x12\x11\n\tm_rd_peak\x18\r \x01(\r\x12\x13\n\x0bm_wr_as_avg\x18\x0e \x01(\r\x12\x13\n\x0bm_wr_as_cnt\x18\x0f \x01(\r\x12\x14\n\x0cm_wr_as_peak\x18\x10 \x01(\r\x12\x12\n\nm_wr_s_avg\x18\x11 \x01(\r\x12\x12\n\nm_wr_s_cnt\x18\x12 \x01(\r\x12\x13\n\x0bm_wr_s_peak\x18\x13 \x01(\r\x12\x10\n\x08n_rd_avg\x18\x14 \x01(\r\x12\x10\n\x08n_rd_cnt\x18\x15 \x01(\r\x12\x11\n\tn_rd_peak\x18\x16 \x01(\r\x12\x13\n\x0bn_wr_as_avg\x18\x17 \x01(\r\x12\x13\n\x0bn_wr_as_cnt\x18\x18 \x01(\r\x12\x14\n\x0cn_wr_as_peak\x18\x19 \x01(\r\x12\x12\n\nn_wr_s_avg\x18\x1a \x01(\r\x12\x12\n\nn_wr_s_cnt\x18\x1b \x01(\r\x12\x13\n\x0bn_wr_s_peak\x18\x1c \x01(\r"Z\n\x1b\x46\x32\x66sBackgroundGcFtraceEvent\x12\x0b\n\x03\x64\x65v\x18\x01 \x01(\x04\x12\x0f\n\x07wait_ms\x18\x02 \x01(\r\x12\x0f\n\x07prefree\x18\x03 \x01(\r\x12\x0c\n\x04\x66ree\x18\x04 \x01(\r"\x8e\x02\n\x16\x46\x32\x66sGcBeginFtraceEvent\x12\x0b\n\x03\x64\x65v\x18\x01 \x01(\x04\x12\x0c\n\x04sync\x18\x02 \x01(\r\x12\x12\n\nbackground\x18\x03 \x01(\r\x12\x13\n\x0b\x64irty_nodes\x18\x04 \x01(\x03\x12\x13\n\x0b\x64irty_dents\x18\x05 \x01(\x03\x12\x13\n\x0b\x64irty_imeta\x18\x06 \x01(\x03\x12\x10\n\x08\x66ree_sec\x18\x07 \x01(\r\x12\x10\n\x08\x66ree_seg\x18\x08 \x01(\r\x12\x14\n\x0creserved_seg\x18\t \x01(\x05\x12\x13\n\x0bprefree_seg\x18\n \x01(\r\x12\x0f\n\x07gc_type\x18\x0b \x01(\x05\x12\x10\n\x08no_bg_gc\x18\x0c \x01(\r\x12\x14\n\x0cnr_free_secs\x18\r \x01(\r"\xe4\x01\n\x14\x46\x32\x66sGcEndFtraceEvent\x12\x0b\n\x03\x64\x65v\x18\x01 \x01(\x04\x12\x0b\n\x03ret\x18\x02 \x01(\x05\x12\x11\n\tseg_freed\x18\x03 \x01(\x05\x12\x11\n\tsec_freed\x18\x04 \x01(\x05\x12\x13\n\x0b\x64irty_nodes\x18\x05 \x01(\x03\x12\x13\n\x0b\x64irty_dents\x18\x06 \x01(\x03\x12\x13\n\x0b\x64irty_imeta\x18\x07 \x01(\x03\x12\x10\n\x08\x66ree_sec\x18\x08 \x01(\r\x12\x10\n\x08\x66ree_seg\x18\t \x01(\r\x12\x14\n\x0creserved_seg\x18\n \x01(\x05\x12\x13\n\x0bprefree_seg\x18\x0b \x01(\r"N\n\x19\x46\x61strpcDmaStatFtraceEvent\x12\x0b\n\x03\x63id\x18\x01 \x01(\x05\x12\x0b\n\x03len\x18\x02 \x01(\x03\x12\x17\n\x0ftotal_allocated\x18\x03 \x01(\x04"D\n\x19\x46\x61strpcDmaFreeFtraceEvent\x12\x0b\n\x03\x63id\x18\x01 \x01(\x05\x12\x0c\n\x04phys\x18\x02 \x01(\x04\x12\x0c\n\x04size\x18\x03 \x01(\x04"c\n\x1a\x46\x61strpcDmaAllocFtraceEvent\x12\x0b\n\x03\x63id\x18\x01 \x01(\x05\x12\x0c\n\x04phys\x18\x02 \x01(\x04\x12\x0c\n\x04size\x18\x03 \x01(\x04\x12\x0c\n\x04\x61ttr\x18\x04 \x01(\x04\x12\x0e\n\x06mflags\x18\x05 \x01(\x05"E\n\x1a\x46\x61strpcDmaUnmapFtraceEvent\x12\x0b\n\x03\x63id\x18\x01 \x01(\x05\x12\x0c\n\x04phys\x18\x02 \x01(\x04\x12\x0c\n\x04size\x18\x03 \x01(\x04"z\n\x18\x46\x61strpcDmaMapFtraceEvent\x12\x0b\n\x03\x63id\x18\x01 \x01(\x05\x12\n\n\x02\x66\x64\x18\x02 \x01(\x05\x12\x0c\n\x04phys\x18\x03 \x01(\x04\x12\x0c\n\x04size\x18\x04 \x01(\x04\x12\x0b\n\x03len\x18\x05 \x01(\x04\x12\x0c\n\x04\x61ttr\x18\x06 \x01(\r\x12\x0e\n\x06mflags\x18\x07 \x01(\x05"X\n\x14\x46\x65nceInitFtraceEvent\x12\x0f\n\x07\x63ontext\x18\x01 \x01(\r\x12\x0e\n\x06\x64river\x18\x02 \x01(\t\x12\r\n\x05seqno\x18\x03 \x01(\r\x12\x10\n\x08timeline\x18\x04 \x01(\t"[\n\x17\x46\x65nceDestroyFtraceEvent\x12\x0f\n\x07\x63ontext\x18\x01 \x01(\r\x12\x0e\n\x06\x64river\x18\x02 \x01(\t\x12\r\n\x05seqno\x18\x03 \x01(\r\x12\x10\n\x08timeline\x18\x04 \x01(\t"`\n\x1c\x46\x65nceEnableSignalFtraceEvent\x12\x0f\n\x07\x63ontext\x18\x01 \x01(\r\x12\x0e\n\x06\x64river\x18\x02 \x01(\t\x12\r\n\x05seqno\x18\x03 \x01(\r\x12\x10\n\x08timeline\x18\x04 \x01(\t"\\\n\x18\x46\x65nceSignaledFtraceEvent\x12\x0f\n\x07\x63ontext\x18\x01 \x01(\r\x12\x0e\n\x06\x64river\x18\x02 \x01(\t\x12\r\n\x05seqno\x18\x03 \x01(\r\x12\x10\n\x08timeline\x18\x04 \x01(\t"l\n"MmFilemapAddToPageCacheFtraceEvent\x12\x0b\n\x03pfn\x18\x01 \x01(\x04\x12\r\n\x05i_ino\x18\x02 \x01(\x04\x12\r\n\x05index\x18\x03 \x01(\x04\x12\r\n\x05s_dev\x18\x04 \x01(\x04\x12\x0c\n\x04page\x18\x05 \x01(\x04"q\n\'MmFilemapDeleteFromPageCacheFtraceEvent\x12\x0b\n\x03pfn\x18\x01 \x01(\x04\x12\r\n\x05i_ino\x18\x02 \x01(\x04\x12\r\n\x05index\x18\x03 \x01(\x04\x12\r\n\x05s_dev\x18\x04 \x01(\x04\x12\x0c\n\x04page\x18\x05 \x01(\x04"+\n\x10PrintFtraceEvent\x12\n\n\x02ip\x18\x01 \x01(\x04\x12\x0b\n\x03\x62uf\x18\x02 \x01(\t"8\n\x19\x46uncgraphEntryFtraceEvent\x12\r\n\x05\x64\x65pth\x18\x01 \x01(\x05\x12\x0c\n\x04\x66unc\x18\x02 \x01(\x04"k\n\x18\x46uncgraphExitFtraceEvent\x12\x10\n\x08\x63\x61lltime\x18\x01 \x01(\x04\x12\r\n\x05\x64\x65pth\x18\x02 \x01(\x05\x12\x0c\n\x04\x66unc\x18\x03 \x01(\x04\x12\x0f\n\x07overrun\x18\x04 \x01(\x04\x12\x0f\n\x07rettime\x18\x05 \x01(\x04"X\n\x1eG2dTracingMarkWriteFtraceEvent\x12\x0b\n\x03pid\x18\x01 \x01(\x05\x12\x0c\n\x04name\x18\x04 \x01(\t\x12\x0c\n\x04type\x18\x05 \x01(\r\x12\r\n\x05value\x18\x06 \x01(\x05"\xc2\x01\n\x12GenericFtraceEvent\x12\x12\n\nevent_name\x18\x01 \x01(\t\x12\x38\n\x05\x66ield\x18\x02 \x03(\x0b\x32).perfetto.protos.GenericFtraceEvent.Field\x1a^\n\x05\x46ield\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x13\n\tstr_value\x18\x03 \x01(\tH\x00\x12\x13\n\tint_value\x18\x04 \x01(\x03H\x00\x12\x14\n\nuint_value\x18\x05 \x01(\x04H\x00\x42\x07\n\x05value"=\n\x19GoogleIccEventFtraceEvent\x12\r\n\x05\x65vent\x18\x01 \x01(\t\x12\x11\n\ttimestamp\x18\x02 \x01(\x04"=\n\x19GoogleIrmEventFtraceEvent\x12\r\n\x05\x65vent\x18\x01 \x01(\t\x12\x11\n\ttimestamp\x18\x02 \x01(\x04"C\n\x16GpuMemTotalFtraceEvent\x12\x0e\n\x06gpu_id\x18\x01 \x01(\r\x12\x0b\n\x03pid\x18\x02 \x01(\r\x12\x0c\n\x04size\x18\x03 \x01(\x04"z\n\x16\x44rmSchedJobFtraceEvent\x12\x0e\n\x06\x65ntity\x18\x01 \x01(\x04\x12\r\n\x05\x66\x65nce\x18\x02 \x01(\x04\x12\x14\n\x0chw_job_count\x18\x03 \x01(\x05\x12\n\n\x02id\x18\x04 \x01(\x04\x12\x11\n\tjob_count\x18\x05 \x01(\r\x12\x0c\n\x04name\x18\x06 \x01(\t"x\n\x14\x44rmRunJobFtraceEvent\x12\x0e\n\x06\x65ntity\x18\x01 \x01(\x04\x12\r\n\x05\x66\x65nce\x18\x02 \x01(\x04\x12\x14\n\x0chw_job_count\x18\x03 \x01(\x05\x12\n\n\x02id\x18\x04 \x01(\x04\x12\x11\n\tjob_count\x18\x05 \x01(\r\x12\x0c\n\x04name\x18\x06 \x01(\t".\n\x1d\x44rmSchedProcessJobFtraceEvent\x12\r\n\x05\x66\x65nce\x18\x01 \x01(\x04"\x15\n\x13HypEnterFtraceEvent"\x14\n\x12HypExitFtraceEvent"3\n\x14HostHcallFtraceEvent\x12\n\n\x02id\x18\x01 \x01(\r\x12\x0f\n\x07invalid\x18\x02 \x01(\r"3\n\x12HostSmcFtraceEvent\x12\n\n\x02id\x18\x01 \x01(\x04\x12\x11\n\tforwarded\x18\x02 \x01(\r"4\n\x17HostMemAbortFtraceEvent\x12\x0b\n\x03\x65sr\x18\x01 \x01(\x04\x12\x0c\n\x04\x61\x64\x64r\x18\x02 \x01(\x04"b\n\x12I2cReadFtraceEvent\x12\x12\n\nadapter_nr\x18\x01 \x01(\x05\x12\x0e\n\x06msg_nr\x18\x02 \x01(\r\x12\x0c\n\x04\x61\x64\x64r\x18\x03 \x01(\r\x12\r\n\x05\x66lags\x18\x04 \x01(\r\x12\x0b\n\x03len\x18\x05 \x01(\r"p\n\x13I2cWriteFtraceEvent\x12\x12\n\nadapter_nr\x18\x01 \x01(\x05\x12\x0e\n\x06msg_nr\x18\x02 \x01(\r\x12\x0c\n\x04\x61\x64\x64r\x18\x03 \x01(\r\x12\r\n\x05\x66lags\x18\x04 \x01(\r\x12\x0b\n\x03len\x18\x05 \x01(\r\x12\x0b\n\x03\x62uf\x18\x06 \x01(\r"H\n\x14I2cResultFtraceEvent\x12\x12\n\nadapter_nr\x18\x01 \x01(\x05\x12\x0f\n\x07nr_msgs\x18\x02 \x01(\r\x12\x0b\n\x03ret\x18\x03 \x01(\x05"p\n\x13I2cReplyFtraceEvent\x12\x12\n\nadapter_nr\x18\x01 \x01(\x05\x12\x0e\n\x06msg_nr\x18\x02 \x01(\r\x12\x0c\n\x04\x61\x64\x64r\x18\x03 \x01(\r\x12\r\n\x05\x66lags\x18\x04 \x01(\r\x12\x0b\n\x03len\x18\x05 \x01(\r\x12\x0b\n\x03\x62uf\x18\x06 \x01(\r"j\n\x14SmbusReadFtraceEvent\x12\x12\n\nadapter_nr\x18\x01 \x01(\x05\x12\r\n\x05\x66lags\x18\x02 \x01(\r\x12\x0c\n\x04\x61\x64\x64r\x18\x03 \x01(\r\x12\x0f\n\x07\x63ommand\x18\x04 \x01(\r\x12\x10\n\x08protocol\x18\x05 \x01(\r"x\n\x15SmbusWriteFtraceEvent\x12\x12\n\nadapter_nr\x18\x01 \x01(\x05\x12\x0c\n\x04\x61\x64\x64r\x18\x02 \x01(\r\x12\r\n\x05\x66lags\x18\x03 \x01(\r\x12\x0f\n\x07\x63ommand\x18\x04 \x01(\r\x12\x0b\n\x03len\x18\x05 \x01(\r\x12\x10\n\x08protocol\x18\x06 \x01(\r"\x8d\x01\n\x16SmbusResultFtraceEvent\x12\x12\n\nadapter_nr\x18\x01 \x01(\x05\x12\x0c\n\x04\x61\x64\x64r\x18\x02 \x01(\r\x12\r\n\x05\x66lags\x18\x03 \x01(\r\x12\x12\n\nread_write\x18\x04 \x01(\r\x12\x0f\n\x07\x63ommand\x18\x05 \x01(\r\x12\x0b\n\x03res\x18\x06 \x01(\x05\x12\x10\n\x08protocol\x18\x07 \x01(\r"x\n\x15SmbusReplyFtraceEvent\x12\x12\n\nadapter_nr\x18\x01 \x01(\x05\x12\x0c\n\x04\x61\x64\x64r\x18\x02 \x01(\r\x12\r\n\x05\x66lags\x18\x03 \x01(\r\x12\x0f\n\x07\x63ommand\x18\x04 \x01(\r\x12\x0b\n\x03len\x18\x05 \x01(\r\x12\x10\n\x08protocol\x18\x06 \x01(\r"M\n\x12IonStatFtraceEvent\x12\x11\n\tbuffer_id\x18\x01 \x01(\r\x12\x0b\n\x03len\x18\x02 \x01(\x03\x12\x17\n\x0ftotal_allocated\x18\x03 \x01(\x04"%\n\x13IpiEntryFtraceEvent\x12\x0e\n\x06reason\x18\x01 \x01(\t"$\n\x12IpiExitFtraceEvent\x12\x0e\n\x06reason\x18\x01 \x01(\t":\n\x13IpiRaiseFtraceEvent\x12\x13\n\x0btarget_cpus\x18\x01 \x01(\r\x12\x0e\n\x06reason\x18\x02 \x01(\t"&\n\x17SoftirqEntryFtraceEvent\x12\x0b\n\x03vec\x18\x01 \x01(\r"%\n\x16SoftirqExitFtraceEvent\x12\x0b\n\x03vec\x18\x01 \x01(\r"&\n\x17SoftirqRaiseFtraceEvent\x12\x0b\n\x03vec\x18\x01 \x01(\r"H\n\x1aIrqHandlerEntryFtraceEvent\x12\x0b\n\x03irq\x18\x01 \x01(\x05\x12\x0c\n\x04name\x18\x02 \x01(\t\x12\x0f\n\x07handler\x18\x03 \x01(\r"5\n\x19IrqHandlerExitFtraceEvent\x12\x0b\n\x03irq\x18\x01 \x01(\x05\x12\x0b\n\x03ret\x18\x02 \x01(\x05"?\n\x1bKgslGpuFrequencyFtraceEvent\x12\x10\n\x08gpu_freq\x18\x01 \x01(\r\x12\x0e\n\x06gpu_id\x18\x02 \x01(\r"q\n#KgslAdrenoCmdbatchQueuedFtraceEvent\x12\n\n\x02id\x18\x01 \x01(\r\x12\x11\n\ttimestamp\x18\x02 \x01(\r\x12\x0e\n\x06queued\x18\x03 \x01(\r\x12\r\n\x05\x66lags\x18\x04 \x01(\r\x12\x0c\n\x04prio\x18\x05 \x01(\r"\xf9\x01\n&KgslAdrenoCmdbatchSubmittedFtraceEvent\x12\n\n\x02id\x18\x01 \x01(\r\x12\x11\n\ttimestamp\x18\x02 \x01(\r\x12\x10\n\x08inflight\x18\x03 \x01(\x03\x12\r\n\x05\x66lags\x18\x04 \x01(\r\x12\r\n\x05ticks\x18\x05 \x01(\x04\x12\x0c\n\x04secs\x18\x06 \x01(\x04\x12\r\n\x05usecs\x18\x07 \x01(\x04\x12\x0c\n\x04prio\x18\x08 \x01(\x05\x12\r\n\x05rb_id\x18\t \x01(\x05\x12\x0c\n\x04rptr\x18\n \x01(\r\x12\x0c\n\x04wptr\x18\x0b \x01(\r\x12\x12\n\nq_inflight\x18\x0c \x01(\x05\x12\x16\n\x0e\x64ispatch_queue\x18\r \x01(\x05"_\n!KgslAdrenoCmdbatchSyncFtraceEvent\x12\n\n\x02id\x18\x01 \x01(\r\x12\x11\n\ttimestamp\x18\x02 \x01(\r\x12\r\n\x05ticks\x18\x03 \x01(\x04\x12\x0c\n\x04prio\x18\x04 \x01(\x05"\xd5\x02\n$KgslAdrenoCmdbatchRetiredFtraceEvent\x12\n\n\x02id\x18\x01 \x01(\r\x12\x11\n\ttimestamp\x18\x02 \x01(\r\x12\x10\n\x08inflight\x18\x03 \x01(\x03\x12\x10\n\x08recovery\x18\x04 \x01(\r\x12\r\n\x05\x66lags\x18\x05 \x01(\r\x12\r\n\x05start\x18\x06 \x01(\x04\x12\x0e\n\x06retire\x18\x07 \x01(\x04\x12\x0c\n\x04prio\x18\x08 \x01(\x05\x12\r\n\x05rb_id\x18\t \x01(\x05\x12\x0c\n\x04rptr\x18\n \x01(\r\x12\x0c\n\x04wptr\x18\x0b \x01(\r\x12\x12\n\nq_inflight\x18\x0c \x01(\x05\x12\x16\n\x0e\x66\x61ult_recovery\x18\r \x01(\x04\x12\x16\n\x0e\x64ispatch_queue\x18\x0e \x01(\r\x12\x17\n\x0fsubmitted_to_rb\x18\x0f \x01(\x04\x12\x16\n\x0eretired_on_gmu\x18\x10 \x01(\x04\x12\x0e\n\x06\x61\x63tive\x18\x11 \x01(\x04"A\n\x1d\x41llocPagesIommuEndFtraceEvent\x12\x11\n\tgfp_flags\x18\x01 \x01(\r\x12\r\n\x05order\x18\x02 \x01(\r"B\n\x1e\x41llocPagesIommuFailFtraceEvent\x12\x11\n\tgfp_flags\x18\x01 \x01(\r\x12\r\n\x05order\x18\x02 \x01(\r"C\n\x1f\x41llocPagesIommuStartFtraceEvent\x12\x11\n\tgfp_flags\x18\x01 \x01(\r\x12\r\n\x05order\x18\x02 \x01(\r"?\n\x1b\x41llocPagesSysEndFtraceEvent\x12\x11\n\tgfp_flags\x18\x01 \x01(\r\x12\r\n\x05order\x18\x02 \x01(\r"@\n\x1c\x41llocPagesSysFailFtraceEvent\x12\x11\n\tgfp_flags\x18\x01 \x01(\r\x12\r\n\x05order\x18\x02 \x01(\r"A\n\x1d\x41llocPagesSysStartFtraceEvent\x12\x11\n\tgfp_flags\x18\x01 \x01(\r\x12\r\n\x05order\x18\x02 \x01(\r"3\n"DmaAllocContiguousRetryFtraceEvent\x12\r\n\x05tries\x18\x01 \x01(\x05"S\n\x18IommuMapRangeFtraceEvent\x12\x12\n\nchunk_size\x18\x01 \x01(\x04\x12\x0b\n\x03len\x18\x02 \x01(\x04\x12\n\n\x02pa\x18\x03 \x01(\x04\x12\n\n\x02va\x18\x04 \x01(\x04"f\n"IommuSecPtblMapRangeEndFtraceEvent\x12\x0b\n\x03len\x18\x01 \x01(\x04\x12\x0b\n\x03num\x18\x02 \x01(\x05\x12\n\n\x02pa\x18\x03 \x01(\r\x12\x0e\n\x06sec_id\x18\x04 \x01(\x05\x12\n\n\x02va\x18\x05 \x01(\x04"h\n$IommuSecPtblMapRangeStartFtraceEvent\x12\x0b\n\x03len\x18\x01 \x01(\x04\x12\x0b\n\x03num\x18\x02 \x01(\x05\x12\n\n\x02pa\x18\x03 \x01(\r\x12\x0e\n\x06sec_id\x18\x04 \x01(\x05\x12\n\n\x02va\x18\x05 \x01(\x04"p\n\x1cIonAllocBufferEndFtraceEvent\x12\x13\n\x0b\x63lient_name\x18\x01 \x01(\t\x12\r\n\x05\x66lags\x18\x02 \x01(\r\x12\x11\n\theap_name\x18\x03 \x01(\t\x12\x0b\n\x03len\x18\x04 \x01(\x04\x12\x0c\n\x04mask\x18\x05 \x01(\r"\x80\x01\n\x1dIonAllocBufferFailFtraceEvent\x12\x13\n\x0b\x63lient_name\x18\x01 \x01(\t\x12\r\n\x05\x65rror\x18\x02 \x01(\x03\x12\r\n\x05\x66lags\x18\x03 \x01(\r\x12\x11\n\theap_name\x18\x04 \x01(\t\x12\x0b\n\x03len\x18\x05 \x01(\x04\x12\x0c\n\x04mask\x18\x06 \x01(\r"\x84\x01\n!IonAllocBufferFallbackFtraceEvent\x12\x13\n\x0b\x63lient_name\x18\x01 \x01(\t\x12\r\n\x05\x65rror\x18\x02 \x01(\x03\x12\r\n\x05\x66lags\x18\x03 \x01(\r\x12\x11\n\theap_name\x18\x04 \x01(\t\x12\x0b\n\x03len\x18\x05 \x01(\x04\x12\x0c\n\x04mask\x18\x06 \x01(\r"r\n\x1eIonAllocBufferStartFtraceEvent\x12\x13\n\x0b\x63lient_name\x18\x01 \x01(\t\x12\r\n\x05\x66lags\x18\x02 \x01(\r\x12\x11\n\theap_name\x18\x03 \x01(\t\x12\x0b\n\x03len\x18\x04 \x01(\x04\x12\x0c\n\x04mask\x18\x05 \x01(\r"+\n\x1aIonCpAllocRetryFtraceEvent\x12\r\n\x05tries\x18\x01 \x01(\x05"_\n\x1fIonCpSecureBufferEndFtraceEvent\x12\r\n\x05\x61lign\x18\x01 \x01(\x04\x12\r\n\x05\x66lags\x18\x02 \x01(\x04\x12\x11\n\theap_name\x18\x03 \x01(\t\x12\x0b\n\x03len\x18\x04 \x01(\x04"a\n!IonCpSecureBufferStartFtraceEvent\x12\r\n\x05\x61lign\x18\x01 \x01(\x04\x12\r\n\x05\x66lags\x18\x02 \x01(\x04\x12\x11\n\theap_name\x18\x03 \x01(\t\x12\x0b\n\x03len\x18\x04 \x01(\x04"(\n\x19IonPrefetchingFtraceEvent\x12\x0b\n\x03len\x18\x01 \x01(\x04"[\n#IonSecureCmaAddToPoolEndFtraceEvent\x12\x13\n\x0bis_prefetch\x18\x01 \x01(\r\x12\x0b\n\x03len\x18\x02 \x01(\x04\x12\x12\n\npool_total\x18\x03 \x01(\x05"]\n%IonSecureCmaAddToPoolStartFtraceEvent\x12\x13\n\x0bis_prefetch\x18\x01 \x01(\r\x12\x0b\n\x03len\x18\x02 \x01(\x04\x12\x12\n\npool_total\x18\x03 \x01(\x05"b\n"IonSecureCmaAllocateEndFtraceEvent\x12\r\n\x05\x61lign\x18\x01 \x01(\x04\x12\r\n\x05\x66lags\x18\x02 \x01(\x04\x12\x11\n\theap_name\x18\x03 \x01(\t\x12\x0b\n\x03len\x18\x04 \x01(\x04"d\n$IonSecureCmaAllocateStartFtraceEvent\x12\r\n\x05\x61lign\x18\x01 \x01(\x04\x12\r\n\x05\x66lags\x18\x02 \x01(\x04\x12\x11\n\theap_name\x18\x03 \x01(\t\x12\x0b\n\x03len\x18\x04 \x01(\x04"R\n$IonSecureCmaShrinkPoolEndFtraceEvent\x12\x14\n\x0c\x64rained_size\x18\x01 \x01(\x04\x12\x14\n\x0cskipped_size\x18\x02 \x01(\x04"T\n&IonSecureCmaShrinkPoolStartFtraceEvent\x12\x14\n\x0c\x64rained_size\x18\x01 \x01(\x04\x12\x14\n\x0cskipped_size\x18\x02 \x01(\x04"2\n\x10KfreeFtraceEvent\x12\x11\n\tcall_site\x18\x01 \x01(\x04\x12\x0b\n\x03ptr\x18\x02 \x01(\x04"o\n\x12KmallocFtraceEvent\x12\x13\n\x0b\x62ytes_alloc\x18\x01 \x01(\x04\x12\x11\n\tbytes_req\x18\x02 \x01(\x04\x12\x11\n\tcall_site\x18\x03 \x01(\x04\x12\x11\n\tgfp_flags\x18\x04 \x01(\r\x12\x0b\n\x03ptr\x18\x05 \x01(\x04"\x81\x01\n\x16KmallocNodeFtraceEvent\x12\x13\n\x0b\x62ytes_alloc\x18\x01 \x01(\x04\x12\x11\n\tbytes_req\x18\x02 \x01(\x04\x12\x11\n\tcall_site\x18\x03 \x01(\x04\x12\x11\n\tgfp_flags\x18\x04 \x01(\r\x12\x0c\n\x04node\x18\x05 \x01(\x05\x12\x0b\n\x03ptr\x18\x06 \x01(\x04"v\n\x19KmemCacheAllocFtraceEvent\x12\x13\n\x0b\x62ytes_alloc\x18\x01 \x01(\x04\x12\x11\n\tbytes_req\x18\x02 \x01(\x04\x12\x11\n\tcall_site\x18\x03 \x01(\x04\x12\x11\n\tgfp_flags\x18\x04 \x01(\r\x12\x0b\n\x03ptr\x18\x05 \x01(\x04"\x88\x01\n\x1dKmemCacheAllocNodeFtraceEvent\x12\x13\n\x0b\x62ytes_alloc\x18\x01 \x01(\x04\x12\x11\n\tbytes_req\x18\x02 \x01(\x04\x12\x11\n\tcall_site\x18\x03 \x01(\x04\x12\x11\n\tgfp_flags\x18\x04 \x01(\r\x12\x0c\n\x04node\x18\x05 \x01(\x05\x12\x0b\n\x03ptr\x18\x06 \x01(\x04":\n\x18KmemCacheFreeFtraceEvent\x12\x11\n\tcall_site\x18\x01 \x01(\x04\x12\x0b\n\x03ptr\x18\x02 \x01(\x04"*\n\x1aMigratePagesEndFtraceEvent\x12\x0c\n\x04mode\x18\x01 \x01(\x05",\n\x1cMigratePagesStartFtraceEvent\x12\x0c\n\x04mode\x18\x01 \x01(\x05"(\n\x17MigrateRetryFtraceEvent\x12\r\n\x05tries\x18\x01 \x01(\x05"j\n\x16MmPageAllocFtraceEvent\x12\x11\n\tgfp_flags\x18\x01 \x01(\r\x12\x13\n\x0bmigratetype\x18\x02 \x01(\x05\x12\r\n\x05order\x18\x03 \x01(\r\x12\x0c\n\x04page\x18\x04 \x01(\x04\x12\x0b\n\x03pfn\x18\x05 \x01(\x04"\xba\x01\n\x1dMmPageAllocExtfragFtraceEvent\x12\x19\n\x11\x61lloc_migratetype\x18\x01 \x01(\x05\x12\x13\n\x0b\x61lloc_order\x18\x02 \x01(\x05\x12\x1c\n\x14\x66\x61llback_migratetype\x18\x03 \x01(\x05\x12\x16\n\x0e\x66\x61llback_order\x18\x04 \x01(\x05\x12\x0c\n\x04page\x18\x05 \x01(\x04\x12\x18\n\x10\x63hange_ownership\x18\x06 \x01(\x05\x12\x0b\n\x03pfn\x18\x07 \x01(\x04"a\n MmPageAllocZoneLockedFtraceEvent\x12\x13\n\x0bmigratetype\x18\x01 \x01(\x05\x12\r\n\x05order\x18\x02 \x01(\r\x12\x0c\n\x04page\x18\x03 \x01(\x04\x12\x0b\n\x03pfn\x18\x04 \x01(\x04"A\n\x15MmPageFreeFtraceEvent\x12\r\n\x05order\x18\x01 \x01(\r\x12\x0c\n\x04page\x18\x02 \x01(\x04\x12\x0b\n\x03pfn\x18\x03 \x01(\x04"G\n\x1cMmPageFreeBatchedFtraceEvent\x12\x0c\n\x04\x63old\x18\x01 \x01(\x05\x12\x0c\n\x04page\x18\x02 \x01(\x04\x12\x0b\n\x03pfn\x18\x03 \x01(\x04"[\n\x1aMmPagePcpuDrainFtraceEvent\x12\x13\n\x0bmigratetype\x18\x01 \x01(\x05\x12\r\n\x05order\x18\x02 \x01(\r\x12\x0c\n\x04page\x18\x03 \x01(\x04\x12\x0b\n\x03pfn\x18\x04 \x01(\x04"O\n\x12RssStatFtraceEvent\x12\x0e\n\x06member\x18\x01 \x01(\x05\x12\x0c\n\x04size\x18\x02 \x01(\x03\x12\x0c\n\x04\x63urr\x18\x03 \x01(\r\x12\r\n\x05mm_id\x18\x04 \x01(\r"S\n\x18IonHeapShrinkFtraceEvent\x12\x11\n\theap_name\x18\x01 \x01(\t\x12\x0b\n\x03len\x18\x02 \x01(\x04\x12\x17\n\x0ftotal_allocated\x18\x03 \x01(\x03"Q\n\x16IonHeapGrowFtraceEvent\x12\x11\n\theap_name\x18\x01 \x01(\t\x12\x0b\n\x03len\x18\x02 \x01(\x04\x12\x17\n\x0ftotal_allocated\x18\x03 \x01(\x03"7\n\x1aIonBufferCreateFtraceEvent\x12\x0c\n\x04\x61\x64\x64r\x18\x01 \x01(\x04\x12\x0b\n\x03len\x18\x02 \x01(\x04"8\n\x1bIonBufferDestroyFtraceEvent\x12\x0c\n\x04\x61\x64\x64r\x18\x01 \x01(\x04\x12\x0b\n\x03len\x18\x02 \x01(\x04"(\n\x19KvmAccessFaultFtraceEvent\x12\x0b\n\x03ipa\x18\x01 \x01(\x04"4\n\x14KvmAckIrqFtraceEvent\x12\x0f\n\x07irqchip\x18\x01 \x01(\r\x12\x0b\n\x03pin\x18\x02 \x01(\r"2\n\x14KvmAgeHvaFtraceEvent\x12\x0b\n\x03\x65nd\x18\x01 \x01(\x04\x12\r\n\x05start\x18\x02 \x01(\x04"T\n\x15KvmAgePageFtraceEvent\x12\x0b\n\x03gfn\x18\x01 \x01(\x04\x12\x0b\n\x03hva\x18\x02 \x01(\x04\x12\r\n\x05level\x18\x03 \x01(\r\x12\x12\n\nreferenced\x18\x04 \x01(\r"2\n\x1bKvmArmClearDebugFtraceEvent\x12\x13\n\x0bguest_debug\x18\x01 \x01(\r"9\n\x1aKvmArmSetDreg32FtraceEvent\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\r"7\n\x1aKvmArmSetRegsetFtraceEvent\x12\x0b\n\x03len\x18\x01 \x01(\x05\x12\x0c\n\x04name\x18\x02 \x01(\t"@\n\x1bKvmArmSetupDebugFtraceEvent\x12\x13\n\x0bguest_debug\x18\x01 \x01(\r\x12\x0c\n\x04vcpu\x18\x02 \x01(\x04"&\n\x13KvmEntryFtraceEvent\x12\x0f\n\x07vcpu_pc\x18\x01 \x01(\x04"B\n\x12KvmExitFtraceEvent\x12\x0e\n\x06\x65sr_ec\x18\x01 \x01(\r\x12\x0b\n\x03ret\x18\x02 \x01(\x05\x12\x0f\n\x07vcpu_pc\x18\x03 \x01(\x04"!\n\x11KvmFpuFtraceEvent\x12\x0c\n\x04load\x18\x01 \x01(\r"o\n\x19KvmGetTimerMapFtraceEvent\x12\x15\n\rdirect_ptimer\x18\x01 \x01(\x05\x12\x15\n\rdirect_vtimer\x18\x02 \x01(\x05\x12\x13\n\x0b\x65mul_ptimer\x18\x03 \x01(\x05\x12\x0f\n\x07vcpu_id\x18\x04 \x01(\x04"T\n\x18KvmGuestFaultFtraceEvent\x12\x0b\n\x03hsr\x18\x01 \x01(\x04\x12\r\n\x05hxfar\x18\x02 \x01(\x04\x12\x0b\n\x03ipa\x18\x03 \x01(\x04\x12\x0f\n\x07vcpu_pc\x18\x04 \x01(\x04")\n\x1aKvmHandleSysRegFtraceEvent\x12\x0b\n\x03hsr\x18\x01 \x01(\x04"B\n\x16KvmHvcArm64FtraceEvent\x12\x0b\n\x03imm\x18\x01 \x01(\x04\x12\n\n\x02r0\x18\x02 \x01(\x04\x12\x0f\n\x07vcpu_pc\x18\x03 \x01(\x04"W\n\x15KvmIrqLineFtraceEvent\x12\x0f\n\x07irq_num\x18\x01 \x01(\x05\x12\r\n\x05level\x18\x02 \x01(\x05\x12\x0c\n\x04type\x18\x03 \x01(\r\x12\x10\n\x08vcpu_idx\x18\x04 \x01(\x05"I\n\x12KvmMmioFtraceEvent\x12\x0b\n\x03gpa\x18\x01 \x01(\x04\x12\x0b\n\x03len\x18\x02 \x01(\r\x12\x0c\n\x04type\x18\x03 \x01(\r\x12\x0b\n\x03val\x18\x04 \x01(\x04"I\n\x19KvmMmioEmulateFtraceEvent\x12\x0c\n\x04\x63psr\x18\x01 \x01(\x04\x12\r\n\x05instr\x18\x02 \x01(\x04\x12\x0f\n\x07vcpu_pc\x18\x03 \x01(\x04"@\n\x1bKvmSetGuestDebugFtraceEvent\x12\x13\n\x0bguest_debug\x18\x01 \x01(\r\x12\x0c\n\x04vcpu\x18\x02 \x01(\x04"I\n\x14KvmSetIrqFtraceEvent\x12\x0b\n\x03gsi\x18\x01 \x01(\r\x12\x15\n\rirq_source_id\x18\x02 \x01(\x05\x12\r\n\x05level\x18\x03 \x01(\x05"\'\n\x18KvmSetSpteHvaFtraceEvent\x12\x0b\n\x03hva\x18\x01 \x01(\x04";\n\x19KvmSetWayFlushFtraceEvent\x12\r\n\x05\x63\x61\x63he\x18\x01 \x01(\r\x12\x0f\n\x07vcpu_pc\x18\x02 \x01(\x04"\x8b\x01\n\x17KvmSysAccessFtraceEvent\x12\x0b\n\x03\x43Rm\x18\x01 \x01(\r\x12\x0b\n\x03\x43Rn\x18\x02 \x01(\r\x12\x0b\n\x03Op0\x18\x03 \x01(\r\x12\x0b\n\x03Op1\x18\x04 \x01(\r\x12\x0b\n\x03Op2\x18\x05 \x01(\r\x12\x10\n\x08is_write\x18\x06 \x01(\r\x12\x0c\n\x04name\x18\x07 \x01(\t\x12\x0f\n\x07vcpu_pc\x18\x08 \x01(\x04"\'\n\x18KvmTestAgeHvaFtraceEvent\x12\x0b\n\x03hva\x18\x01 \x01(\x04"D\n\x1aKvmTimerEmulateFtraceEvent\x12\x13\n\x0bshould_fire\x18\x01 \x01(\r\x12\x11\n\ttimer_idx\x18\x02 \x01(\x05"5\n KvmTimerHrtimerExpireFtraceEvent\x12\x11\n\ttimer_idx\x18\x01 \x01(\x05"O\n\x1fKvmTimerRestoreStateFtraceEvent\x12\x0b\n\x03\x63tl\x18\x01 \x01(\x04\x12\x0c\n\x04\x63val\x18\x02 \x01(\x04\x12\x11\n\ttimer_idx\x18\x03 \x01(\x05"L\n\x1cKvmTimerSaveStateFtraceEvent\x12\x0b\n\x03\x63tl\x18\x01 \x01(\x04\x12\x0c\n\x04\x63val\x18\x02 \x01(\x04\x12\x11\n\ttimer_idx\x18\x03 \x01(\x05"K\n\x1cKvmTimerUpdateIrqFtraceEvent\x12\x0b\n\x03irq\x18\x01 \x01(\r\x12\r\n\x05level\x18\x02 \x01(\x05\x12\x0f\n\x07vcpu_id\x18\x03 \x01(\x04"F\n\x19KvmToggleCacheFtraceEvent\x12\x0b\n\x03now\x18\x01 \x01(\r\x12\x0f\n\x07vcpu_pc\x18\x02 \x01(\x04\x12\x0b\n\x03was\x18\x03 \x01(\r"9\n\x1bKvmUnmapHvaRangeFtraceEvent\x12\x0b\n\x03\x65nd\x18\x01 \x01(\x04\x12\r\n\x05start\x18\x02 \x01(\x04"-\n\x1bKvmUserspaceExitFtraceEvent\x12\x0e\n\x06reason\x18\x01 \x01(\r"E\n\x18KvmVcpuWakeupFtraceEvent\x12\n\n\x02ns\x18\x01 \x01(\x04\x12\r\n\x05valid\x18\x02 \x01(\r\x12\x0e\n\x06waited\x18\x03 \x01(\r"9\n\x16KvmWfxArm64FtraceEvent\x12\x0e\n\x06is_wfe\x18\x01 \x01(\r\x12\x0f\n\x07vcpu_pc\x18\x02 \x01(\x04"T\n\x12TrapRegFtraceEvent\x12\n\n\x02\x66n\x18\x01 \x01(\t\x12\x10\n\x08is_write\x18\x02 \x01(\r\x12\x0b\n\x03reg\x18\x03 \x01(\x05\x12\x13\n\x0bwrite_value\x18\x04 \x01(\x04"N\n\x1fVgicUpdateIrqPendingFtraceEvent\x12\x0b\n\x03irq\x18\x01 \x01(\r\x12\r\n\x05level\x18\x02 \x01(\r\x12\x0f\n\x07vcpu_id\x18\x03 \x01(\x04"t\n\x18LowmemoryKillFtraceEvent\x12\x0c\n\x04\x63omm\x18\x01 \x01(\t\x12\x0b\n\x03pid\x18\x02 \x01(\x05\x12\x16\n\x0epagecache_size\x18\x03 \x01(\x03\x12\x17\n\x0fpagecache_limit\x18\x04 \x01(\x03\x12\x0c\n\x04\x66ree\x18\x05 \x01(\x03"q\n\x1fLwisTracingMarkWriteFtraceEvent\x12\x11\n\tlwis_name\x18\x01 \x01(\t\x12\x0c\n\x04type\x18\x02 \x01(\r\x12\x0b\n\x03pid\x18\x03 \x01(\x05\x12\x11\n\tfunc_name\x18\x04 \x01(\t\x12\r\n\x05value\x18\x05 \x01(\x03"Y\n\x1fMaliTracingMarkWriteFtraceEvent\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x0b\n\x03pid\x18\x02 \x01(\x05\x12\x0c\n\x04type\x18\x03 \x01(\r\x12\r\n\x05value\x18\x04 \x01(\x05"u\n\x1dMaliMaliKCPUCQSSETFtraceEvent\x12\n\n\x02id\x18\x01 \x01(\r\x12\x11\n\tinfo_val1\x18\x02 \x01(\x04\x12\x11\n\tinfo_val2\x18\x03 \x01(\x04\x12\x0f\n\x07kctx_id\x18\x04 \x01(\r\x12\x11\n\tkctx_tgid\x18\x05 \x01(\x05"{\n#MaliMaliKCPUCQSWAITSTARTFtraceEvent\x12\n\n\x02id\x18\x01 \x01(\r\x12\x11\n\tinfo_val1\x18\x02 \x01(\x04\x12\x11\n\tinfo_val2\x18\x03 \x01(\x04\x12\x0f\n\x07kctx_id\x18\x04 \x01(\r\x12\x11\n\tkctx_tgid\x18\x05 \x01(\x05"y\n!MaliMaliKCPUCQSWAITENDFtraceEvent\x12\n\n\x02id\x18\x01 \x01(\r\x12\x11\n\tinfo_val1\x18\x02 \x01(\x04\x12\x11\n\tinfo_val2\x18\x03 \x01(\x04\x12\x0f\n\x07kctx_id\x18\x04 \x01(\r\x12\x11\n\tkctx_tgid\x18\x05 \x01(\x05"z\n"MaliMaliKCPUFENCESIGNALFtraceEvent\x12\x11\n\tinfo_val1\x18\x01 \x01(\x04\x12\x11\n\tinfo_val2\x18\x02 \x01(\x04\x12\x11\n\tkctx_tgid\x18\x03 \x01(\x05\x12\x0f\n\x07kctx_id\x18\x04 \x01(\r\x12\n\n\x02id\x18\x05 \x01(\r"}\n%MaliMaliKCPUFENCEWAITSTARTFtraceEvent\x12\x11\n\tinfo_val1\x18\x01 \x01(\x04\x12\x11\n\tinfo_val2\x18\x02 \x01(\x04\x12\x11\n\tkctx_tgid\x18\x03 \x01(\x05\x12\x0f\n\x07kctx_id\x18\x04 \x01(\r\x12\n\n\x02id\x18\x05 \x01(\r"{\n#MaliMaliKCPUFENCEWAITENDFtraceEvent\x12\x11\n\tinfo_val1\x18\x01 \x01(\x04\x12\x11\n\tinfo_val2\x18\x02 \x01(\x04\x12\x11\n\tkctx_tgid\x18\x03 \x01(\x05\x12\x0f\n\x07kctx_id\x18\x04 \x01(\r\x12\n\n\x02id\x18\x05 \x01(\r"\\\n$MaliMaliCSFINTERRUPTSTARTFtraceEvent\x12\x11\n\tkctx_tgid\x18\x01 \x01(\x05\x12\x0f\n\x07kctx_id\x18\x02 \x01(\r\x12\x10\n\x08info_val\x18\x03 \x01(\x04"Z\n"MaliMaliCSFINTERRUPTENDFtraceEvent\x12\x11\n\tkctx_tgid\x18\x01 \x01(\x05\x12\x0f\n\x07kctx_id\x18\x02 \x01(\r\x12\x10\n\x08info_val\x18\x03 \x01(\x04"l\n4MaliMaliPMMCUHCTLCORESDOWNSCALENOTIFYPENDFtraceEvent\x12\x11\n\tkctx_tgid\x18\x01 \x01(\x05\x12\x0f\n\x07kctx_id\x18\x02 \x01(\r\x12\x10\n\x08info_val\x18\x03 \x01(\x04"c\n+MaliMaliPMMCUHCTLCORESNOTIFYPENDFtraceEvent\x12\x11\n\tkctx_tgid\x18\x01 \x01(\x05\x12\x0f\n\x07kctx_id\x18\x02 \x01(\r\x12\x10\n\x08info_val\x18\x03 \x01(\x04"d\n,MaliMaliPMMCUHCTLCOREINACTIVEPENDFtraceEvent\x12\x11\n\tkctx_tgid\x18\x01 \x01(\x05\x12\x0f\n\x07kctx_id\x18\x02 \x01(\r\x12\x10\n\x08info_val\x18\x03 \x01(\x04"`\n(MaliMaliPMMCUHCTLMCUONRECHECKFtraceEvent\x12\x11\n\tkctx_tgid\x18\x01 \x01(\x05\x12\x0f\n\x07kctx_id\x18\x02 \x01(\r\x12\x10\n\x08info_val\x18\x03 \x01(\x04"f\n.MaliMaliPMMCUHCTLSHADERSCOREOFFPENDFtraceEvent\x12\x11\n\tkctx_tgid\x18\x01 \x01(\x05\x12\x0f\n\x07kctx_id\x18\x02 \x01(\r\x12\x10\n\x08info_val\x18\x03 \x01(\x04"b\n*MaliMaliPMMCUHCTLSHADERSPENDOFFFtraceEvent\x12\x11\n\tkctx_tgid\x18\x01 \x01(\x05\x12\x0f\n\x07kctx_id\x18\x02 \x01(\r\x12\x10\n\x08info_val\x18\x03 \x01(\x04"a\n)MaliMaliPMMCUHCTLSHADERSPENDONFtraceEvent\x12\x11\n\tkctx_tgid\x18\x01 \x01(\x05\x12\x0f\n\x07kctx_id\x18\x02 \x01(\r\x12\x10\n\x08info_val\x18\x03 \x01(\x04"c\n+MaliMaliPMMCUHCTLSHADERSREADYOFFFtraceEvent\x12\x11\n\tkctx_tgid\x18\x01 \x01(\x05\x12\x0f\n\x07kctx_id\x18\x02 \x01(\r\x12\x10\n\x08info_val\x18\x03 \x01(\x04"W\n\x1fMaliMaliPMMCUINSLEEPFtraceEvent\x12\x11\n\tkctx_tgid\x18\x01 \x01(\x05\x12\x0f\n\x07kctx_id\x18\x02 \x01(\r\x12\x10\n\x08info_val\x18\x03 \x01(\x04"S\n\x1bMaliMaliPMMCUOFFFtraceEvent\x12\x11\n\tkctx_tgid\x18\x01 \x01(\x05\x12\x0f\n\x07kctx_id\x18\x02 \x01(\r\x12\x10\n\x08info_val\x18\x03 \x01(\x04"R\n\x1aMaliMaliPMMCUONFtraceEvent\x12\x11\n\tkctx_tgid\x18\x01 \x01(\x05\x12\x0f\n\x07kctx_id\x18\x02 \x01(\r\x12\x10\n\x08info_val\x18\x03 \x01(\x04"d\n,MaliMaliPMMCUONCOREATTRUPDATEPENDFtraceEvent\x12\x11\n\tkctx_tgid\x18\x01 \x01(\x05\x12\x0f\n\x07kctx_id\x18\x02 \x01(\r\x12\x10\n\x08info_val\x18\x03 \x01(\x04"_\n\'MaliMaliPMMCUONGLBREINITPENDFtraceEvent\x12\x11\n\tkctx_tgid\x18\x01 \x01(\x05\x12\x0f\n\x07kctx_id\x18\x02 \x01(\r\x12\x10\n\x08info_val\x18\x03 \x01(\x04"V\n\x1eMaliMaliPMMCUONHALTFtraceEvent\x12\x11\n\tkctx_tgid\x18\x01 \x01(\x05\x12\x0f\n\x07kctx_id\x18\x02 \x01(\r\x12\x10\n\x08info_val\x18\x03 \x01(\x04"^\n&MaliMaliPMMCUONHWCNTDISABLEFtraceEvent\x12\x11\n\tkctx_tgid\x18\x01 \x01(\x05\x12\x0f\n\x07kctx_id\x18\x02 \x01(\r\x12\x10\n\x08info_val\x18\x03 \x01(\x04"]\n%MaliMaliPMMCUONHWCNTENABLEFtraceEvent\x12\x11\n\tkctx_tgid\x18\x01 \x01(\x05\x12\x0f\n\x07kctx_id\x18\x02 \x01(\r\x12\x10\n\x08info_val\x18\x03 \x01(\x04"Z\n"MaliMaliPMMCUONPENDHALTFtraceEvent\x12\x11\n\tkctx_tgid\x18\x01 \x01(\x05\x12\x0f\n\x07kctx_id\x18\x02 \x01(\r\x12\x10\n\x08info_val\x18\x03 \x01(\x04"[\n#MaliMaliPMMCUONPENDSLEEPFtraceEvent\x12\x11\n\tkctx_tgid\x18\x01 \x01(\x05\x12\x0f\n\x07kctx_id\x18\x02 \x01(\r\x12\x10\n\x08info_val\x18\x03 \x01(\x04"_\n\'MaliMaliPMMCUONSLEEPINITIATEFtraceEvent\x12\x11\n\tkctx_tgid\x18\x01 \x01(\x05\x12\x0f\n\x07kctx_id\x18\x02 \x01(\r\x12\x10\n\x08info_val\x18\x03 \x01(\x04"W\n\x1fMaliMaliPMMCUPENDOFFFtraceEvent\x12\x11\n\tkctx_tgid\x18\x01 \x01(\x05\x12\x0f\n\x07kctx_id\x18\x02 \x01(\r\x12\x10\n\x08info_val\x18\x03 \x01(\x04"\\\n$MaliMaliPMMCUPENDONRELOADFtraceEvent\x12\x11\n\tkctx_tgid\x18\x01 \x01(\x05\x12\x0f\n\x07kctx_id\x18\x02 \x01(\r\x12\x10\n\x08info_val\x18\x03 \x01(\x04"Y\n!MaliMaliPMMCUPOWERDOWNFtraceEvent\x12\x11\n\tkctx_tgid\x18\x01 \x01(\x05\x12\x0f\n\x07kctx_id\x18\x02 \x01(\r\x12\x10\n\x08info_val\x18\x03 \x01(\x04"Y\n!MaliMaliPMMCURESETWAITFtraceEvent\x12\x11\n\tkctx_tgid\x18\x01 \x01(\x05\x12\x0f\n\x07kctx_id\x18\x02 \x01(\r\x12\x10\n\x08info_val\x18\x03 \x01(\x04"@\n\x18MdpCmdKickoffFtraceEvent\x12\x0f\n\x07\x63tl_num\x18\x01 \x01(\r\x12\x13\n\x0bkickoff_cnt\x18\x02 \x01(\x05"Z\n\x14MdpCommitFtraceEvent\x12\x0b\n\x03num\x18\x01 \x01(\r\x12\x10\n\x08play_cnt\x18\x02 \x01(\r\x12\x10\n\x08\x63lk_rate\x18\x03 \x01(\r\x12\x11\n\tbandwidth\x18\x04 \x01(\x04"[\n\x17MdpPerfSetOtFtraceEvent\x12\x0c\n\x04pnum\x18\x01 \x01(\r\x12\x0e\n\x06xin_id\x18\x02 \x01(\r\x12\x0e\n\x06rd_lim\x18\x03 \x01(\r\x12\x12\n\nis_vbif_rt\x18\x04 \x01(\r"\x8c\x02\n\x18MdpSsppChangeFtraceEvent\x12\x0b\n\x03num\x18\x01 \x01(\r\x12\x10\n\x08play_cnt\x18\x02 \x01(\r\x12\r\n\x05mixer\x18\x03 \x01(\r\x12\r\n\x05stage\x18\x04 \x01(\r\x12\r\n\x05\x66lags\x18\x05 \x01(\r\x12\x0e\n\x06\x66ormat\x18\x06 \x01(\r\x12\r\n\x05img_w\x18\x07 \x01(\r\x12\r\n\x05img_h\x18\x08 \x01(\r\x12\r\n\x05src_x\x18\t \x01(\r\x12\r\n\x05src_y\x18\n \x01(\r\x12\r\n\x05src_w\x18\x0b \x01(\r\x12\r\n\x05src_h\x18\x0c \x01(\r\x12\r\n\x05\x64st_x\x18\r \x01(\r\x12\r\n\x05\x64st_y\x18\x0e \x01(\r\x12\r\n\x05\x64st_w\x18\x0f \x01(\r\x12\r\n\x05\x64st_h\x18\x10 \x01(\r"S\n\x1bTracingMarkWriteFtraceEvent\x12\x0b\n\x03pid\x18\x01 \x01(\x05\x12\x12\n\ntrace_name\x18\x02 \x01(\t\x12\x13\n\x0btrace_begin\x18\x03 \x01(\r"d\n\x1dMdpCmdPingpongDoneFtraceEvent\x12\x0f\n\x07\x63tl_num\x18\x01 \x01(\r\x12\x10\n\x08intf_num\x18\x02 \x01(\r\x12\x0e\n\x06pp_num\x18\x03 \x01(\r\x12\x10\n\x08koff_cnt\x18\x04 \x01(\x05"\xa4\x01\n\x17MdpCompareBwFtraceEvent\x12\x0e\n\x06new_ab\x18\x01 \x01(\x04\x12\x0e\n\x06new_ib\x18\x02 \x01(\x04\x12\x0e\n\x06new_wb\x18\x03 \x01(\x04\x12\x0e\n\x06old_ab\x18\x04 \x01(\x04\x12\x0e\n\x06old_ib\x18\x05 \x01(\x04\x12\x0e\n\x06old_wb\x18\x06 \x01(\x04\x12\x16\n\x0eparams_changed\x18\x07 \x01(\r\x12\x11\n\tupdate_bw\x18\x08 \x01(\r"p\n\x1eMdpPerfSetPanicLutsFtraceEvent\x12\x0c\n\x04pnum\x18\x01 \x01(\r\x12\x0b\n\x03\x66mt\x18\x02 \x01(\r\x12\x0c\n\x04mode\x18\x03 \x01(\r\x12\x11\n\tpanic_lut\x18\x04 \x01(\r\x12\x12\n\nrobust_lut\x18\x05 \x01(\r"\x89\x02\n\x15MdpSsppSetFtraceEvent\x12\x0b\n\x03num\x18\x01 \x01(\r\x12\x10\n\x08play_cnt\x18\x02 \x01(\r\x12\r\n\x05mixer\x18\x03 \x01(\r\x12\r\n\x05stage\x18\x04 \x01(\r\x12\r\n\x05\x66lags\x18\x05 \x01(\r\x12\x0e\n\x06\x66ormat\x18\x06 \x01(\r\x12\r\n\x05img_w\x18\x07 \x01(\r\x12\r\n\x05img_h\x18\x08 \x01(\r\x12\r\n\x05src_x\x18\t \x01(\r\x12\r\n\x05src_y\x18\n \x01(\r\x12\r\n\x05src_w\x18\x0b \x01(\r\x12\r\n\x05src_h\x18\x0c \x01(\r\x12\r\n\x05\x64st_x\x18\r \x01(\r\x12\r\n\x05\x64st_y\x18\x0e \x01(\r\x12\r\n\x05\x64st_w\x18\x0f \x01(\r\x12\r\n\x05\x64st_h\x18\x10 \x01(\r"A\n\x1cMdpCmdReadptrDoneFtraceEvent\x12\x0f\n\x07\x63tl_num\x18\x01 \x01(\r\x12\x10\n\x08koff_cnt\x18\x02 \x01(\x05"I\n\x15MdpMisrCrcFtraceEvent\x12\x10\n\x08\x62lock_id\x18\x01 \x01(\r\x12\x11\n\tvsync_cnt\x18\x02 \x01(\r\x12\x0b\n\x03\x63rc\x18\x03 \x01(\r"}\n\x1cMdpPerfSetQosLutsFtraceEvent\x12\x0c\n\x04pnum\x18\x01 \x01(\r\x12\x0b\n\x03\x66mt\x18\x02 \x01(\r\x12\x0c\n\x04intf\x18\x03 \x01(\r\x12\x0b\n\x03rot\x18\x04 \x01(\r\x12\n\n\x02\x66l\x18\x05 \x01(\r\x12\x0b\n\x03lut\x18\x06 \x01(\r\x12\x0e\n\x06linear\x18\x07 \x01(\r"N\n\x1aMdpTraceCounterFtraceEvent\x12\x0b\n\x03pid\x18\x01 \x01(\x05\x12\x14\n\x0c\x63ounter_name\x18\x02 \x01(\t\x12\r\n\x05value\x18\x03 \x01(\x05"-\n\x1aMdpCmdReleaseBwFtraceEvent\x12\x0f\n\x07\x63tl_num\x18\x01 \x01(\r".\n\x19MdpMixerUpdateFtraceEvent\x12\x11\n\tmixer_num\x18\x01 \x01(\r"\xa0\x01\n\x1dMdpPerfSetWmLevelsFtraceEvent\x12\x0c\n\x04pnum\x18\x01 \x01(\r\x12\x11\n\tuse_space\x18\x02 \x01(\r\x12\x16\n\x0epriority_bytes\x18\x03 \x01(\r\x12\x0b\n\x03wm0\x18\x04 \x01(\r\x12\x0b\n\x03wm1\x18\x05 \x01(\r\x12\x0b\n\x03wm2\x18\x06 \x01(\r\x12\x0e\n\x06mb_cnt\x18\x07 \x01(\r\x12\x0f\n\x07mb_size\x18\x08 \x01(\r"H\n\x1fMdpVideoUnderrunDoneFtraceEvent\x12\x0f\n\x07\x63tl_num\x18\x01 \x01(\r\x12\x14\n\x0cunderrun_cnt\x18\x02 \x01(\r"E\n\x1dMdpCmdWaitPingpongFtraceEvent\x12\x0f\n\x07\x63tl_num\x18\x01 \x01(\r\x12\x13\n\x0bkickoff_cnt\x18\x02 \x01(\x05"\xce\x01\n\x1dMdpPerfPrefillCalcFtraceEvent\x12\x0c\n\x04pnum\x18\x01 \x01(\r\x12\x13\n\x0blatency_buf\x18\x02 \x01(\r\x12\n\n\x02ot\x18\x03 \x01(\r\x12\r\n\x05y_buf\x18\x04 \x01(\r\x12\x10\n\x08y_scaler\x18\x05 \x01(\r\x12\x10\n\x08pp_lines\x18\x06 \x01(\r\x12\x10\n\x08pp_bytes\x18\x07 \x01(\r\x12\x0f\n\x07post_sc\x18\x08 \x01(\r\x12\x11\n\tfbc_bytes\x18\t \x01(\r\x12\x15\n\rprefill_bytes\x18\n \x01(\r"Q\n\x1bMdpPerfUpdateBusFtraceEvent\x12\x0e\n\x06\x63lient\x18\x01 \x01(\x05\x12\x10\n\x08\x61\x62_quota\x18\x02 \x01(\x04\x12\x10\n\x08ib_quota\x18\x03 \x01(\x04"0\n\x1fRotatorBwAoAsContextFtraceEvent\x12\r\n\x05state\x18\x01 \x01(\r"Y\n\x18MmEventRecordFtraceEvent\x12\x0f\n\x07\x61vg_lat\x18\x01 \x01(\r\x12\r\n\x05\x63ount\x18\x02 \x01(\r\x12\x0f\n\x07max_lat\x18\x03 \x01(\r\x12\x0c\n\x04type\x18\x04 \x01(\r"H\n\x1aNetifReceiveSkbFtraceEvent\x12\x0b\n\x03len\x18\x01 \x01(\r\x12\x0c\n\x04name\x18\x02 \x01(\t\x12\x0f\n\x07skbaddr\x18\x03 \x01(\x04"O\n\x15NetDevXmitFtraceEvent\x12\x0b\n\x03len\x18\x01 \x01(\r\x12\x0c\n\x04name\x18\x02 \x01(\t\x12\n\n\x02rc\x18\x03 \x01(\x05\x12\x0f\n\x07skbaddr\x18\x04 \x01(\x04"\xfb\x02\n\x1eNapiGroReceiveEntryFtraceEvent\x12\x10\n\x08\x64\x61ta_len\x18\x01 \x01(\r\x12\x10\n\x08gso_size\x18\x02 \x01(\r\x12\x10\n\x08gso_type\x18\x03 \x01(\r\x12\x0c\n\x04hash\x18\x04 \x01(\r\x12\x11\n\tip_summed\x18\x05 \x01(\r\x12\x0f\n\x07l4_hash\x18\x06 \x01(\r\x12\x0b\n\x03len\x18\x07 \x01(\r\x12\x12\n\nmac_header\x18\x08 \x01(\x05\x12\x18\n\x10mac_header_valid\x18\t \x01(\r\x12\x0c\n\x04name\x18\n \x01(\t\x12\x0f\n\x07napi_id\x18\x0b \x01(\r\x12\x10\n\x08nr_frags\x18\x0c \x01(\r\x12\x10\n\x08protocol\x18\r \x01(\r\x12\x15\n\rqueue_mapping\x18\x0e \x01(\r\x12\x0f\n\x07skbaddr\x18\x0f \x01(\x04\x12\x10\n\x08truesize\x18\x10 \x01(\r\x12\x12\n\nvlan_proto\x18\x11 \x01(\r\x12\x13\n\x0bvlan_tagged\x18\x12 \x01(\r\x12\x10\n\x08vlan_tci\x18\x13 \x01(\r",\n\x1dNapiGroReceiveExitFtraceEvent\x12\x0b\n\x03ret\x18\x01 \x01(\x05"P\n\x1cOomScoreAdjUpdateFtraceEvent\x12\x0c\n\x04\x63omm\x18\x01 \x01(\t\x12\x15\n\room_score_adj\x18\x02 \x01(\x05\x12\x0b\n\x03pid\x18\x03 \x01(\x05"$\n\x15MarkVictimFtraceEvent\x12\x0b\n\x03pid\x18\x01 \x01(\x05">\n\x1b\x44siCmdFifoStatusFtraceEvent\x12\x0e\n\x06header\x18\x01 \x01(\r\x12\x0f\n\x07payload\x18\x02 \x01(\r"/\n\x10\x44siRxFtraceEvent\x12\x0b\n\x03\x63md\x18\x01 \x01(\r\x12\x0e\n\x06rx_buf\x18\x02 \x01(\r">\n\x10\x44siTxFtraceEvent\x12\x0c\n\x04last\x18\x01 \x01(\r\x12\x0e\n\x06tx_buf\x18\x02 \x01(\r\x12\x0c\n\x04type\x18\x03 \x01(\r"\x7f\n\x1cPanelWriteGenericFtraceEvent\x12\x0b\n\x03pid\x18\x01 \x01(\x05\x12\x12\n\ntrace_name\x18\x02 \x01(\t\x12\x13\n\x0btrace_begin\x18\x03 \x01(\r\x12\x0c\n\x04name\x18\x04 \x01(\t\x12\x0c\n\x04type\x18\x05 \x01(\r\x12\r\n\x05value\x18\x06 \x01(\x05"\x84\x03\n\x1eSchedSwitchWithCtrsFtraceEvent\x12\x0f\n\x07old_pid\x18\x01 \x01(\x05\x12\x0f\n\x07new_pid\x18\x02 \x01(\x05\x12\x0c\n\x04\x63\x63tr\x18\x03 \x01(\x04\x12\x0c\n\x04\x63tr0\x18\x04 \x01(\x04\x12\x0c\n\x04\x63tr1\x18\x05 \x01(\x04\x12\x0c\n\x04\x63tr2\x18\x06 \x01(\x04\x12\x0c\n\x04\x63tr3\x18\x07 \x01(\x04\x12\r\n\x05lctr0\x18\x08 \x01(\r\x12\r\n\x05lctr1\x18\t \x01(\r\x12\x0c\n\x04\x63tr4\x18\n \x01(\x04\x12\x0c\n\x04\x63tr5\x18\x0b \x01(\x04\x12\x11\n\tprev_comm\x18\x0c \x01(\t\x12\x10\n\x08prev_pid\x18\r \x01(\x05\x12\x0b\n\x03\x63yc\x18\x0e \x01(\r\x12\x0c\n\x04inst\x18\x0f \x01(\r\x12\x0f\n\x07stallbm\x18\x10 \x01(\r\x12\x0c\n\x04l3dm\x18\x11 \x01(\r\x12\x10\n\x08next_pid\x18\x12 \x01(\x05\x12\x11\n\tnext_comm\x18\x13 \x01(\t\x12\x12\n\nprev_state\x18\x14 \x01(\x03\x12\x0c\n\x04\x61mu0\x18\x15 \x01(\x04\x12\x0c\n\x04\x61mu1\x18\x16 \x01(\x04\x12\x0c\n\x04\x61mu2\x18\x17 \x01(\x04"0\n\x1cPixelMmKswapdWakeFtraceEvent\x12\x10\n\x08whatever\x18\x01 \x01(\x05"T\n\x1cPixelMmKswapdDoneFtraceEvent\x12\x18\n\x10\x64\x65lta_nr_scanned\x18\x01 \x01(\x04\x12\x1a\n\x12\x64\x65lta_nr_reclaimed\x18\x02 \x01(\x04"8\n\x17\x43puFrequencyFtraceEvent\x12\r\n\x05state\x18\x01 \x01(\r\x12\x0e\n\x06\x63pu_id\x18\x02 \x01(\r"S\n\x1d\x43puFrequencyLimitsFtraceEvent\x12\x10\n\x08min_freq\x18\x01 \x01(\r\x12\x10\n\x08max_freq\x18\x02 \x01(\r\x12\x0e\n\x06\x63pu_id\x18\x03 \x01(\r"3\n\x12\x43puIdleFtraceEvent\x12\r\n\x05state\x18\x01 \x01(\r\x12\x0e\n\x06\x63pu_id\x18\x02 \x01(\r"E\n\x16\x43lockEnableFtraceEvent\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\r\n\x05state\x18\x02 \x01(\x04\x12\x0e\n\x06\x63pu_id\x18\x03 \x01(\x04"F\n\x17\x43lockDisableFtraceEvent\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\r\n\x05state\x18\x02 \x01(\x04\x12\x0e\n\x06\x63pu_id\x18\x03 \x01(\x04"F\n\x17\x43lockSetRateFtraceEvent\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\r\n\x05state\x18\x02 \x01(\x04\x12\x0e\n\x06\x63pu_id\x18\x03 \x01(\x04"F\n\x18SuspendResumeFtraceEvent\x12\x0e\n\x06\x61\x63tion\x18\x01 \x01(\t\x12\x0b\n\x03val\x18\x02 \x01(\x05\x12\r\n\x05start\x18\x03 \x01(\r"8\n\x17GpuFrequencyFtraceEvent\x12\x0e\n\x06gpu_id\x18\x01 \x01(\r\x12\r\n\x05state\x18\x02 \x01(\r">\n\x1fWakeupSourceActivateFtraceEvent\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\r\n\x05state\x18\x02 \x01(\x04"@\n!WakeupSourceDeactivateFtraceEvent\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\r\n\x05state\x18\x02 \x01(\x04"\x85\x01\n\x18GpuWorkPeriodFtraceEvent\x12\x0e\n\x06gpu_id\x18\x01 \x01(\r\x12\x0b\n\x03uid\x18\x02 \x01(\r\x12\x15\n\rstart_time_ns\x18\x03 \x01(\x04\x12\x13\n\x0b\x65nd_time_ns\x18\x04 \x01(\x04\x12 \n\x18total_active_duration_ns\x18\x05 \x01(\x04"q\n DevicePmCallbackStartFtraceEvent\x12\x0e\n\x06\x64\x65vice\x18\x01 \x01(\t\x12\x0e\n\x06\x64river\x18\x02 \x01(\t\x12\x0e\n\x06parent\x18\x03 \x01(\t\x12\x0e\n\x06pm_ops\x18\x04 \x01(\t\x12\r\n\x05\x65vent\x18\x05 \x01(\x05"O\n\x1e\x44\x65vicePmCallbackEndFtraceEvent\x12\x0e\n\x06\x64\x65vice\x18\x01 \x01(\t\x12\x0e\n\x06\x64river\x18\x02 \x01(\t\x12\r\n\x05\x65rror\x18\x03 \x01(\x05"!\n\x12\x43onsoleFtraceEvent\x12\x0b\n\x03msg\x18\x01 \x01(\t"/\n\x13SysEnterFtraceEvent\x12\n\n\x02id\x18\x01 \x01(\x03\x12\x0c\n\x04\x61rgs\x18\x02 \x03(\x04"-\n\x12SysExitFtraceEvent\x12\n\n\x02id\x18\x01 \x01(\x03\x12\x0b\n\x03ret\x18\x02 \x01(\x03"+\n\x1bRegulatorDisableFtraceEvent\x12\x0c\n\x04name\x18\x01 \x01(\t"3\n#RegulatorDisableCompleteFtraceEvent\x12\x0c\n\x04name\x18\x01 \x01(\t"*\n\x1aRegulatorEnableFtraceEvent\x12\x0c\n\x04name\x18\x01 \x01(\t"2\n"RegulatorEnableCompleteFtraceEvent\x12\x0c\n\x04name\x18\x01 \x01(\t"/\n\x1fRegulatorEnableDelayFtraceEvent\x12\x0c\n\x04name\x18\x01 \x01(\t"H\n\x1eRegulatorSetVoltageFtraceEvent\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x0b\n\x03min\x18\x02 \x01(\x05\x12\x0b\n\x03max\x18\x03 \x01(\x05"C\n&RegulatorSetVoltageCompleteFtraceEvent\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x0b\n\x03val\x18\x02 \x01(\r"4\n\x14RpmStatusFtraceEvent\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x0e\n\x06status\x18\x02 \x01(\x05"}\n"SamsungTracingMarkWriteFtraceEvent\x12\x0b\n\x03pid\x18\x01 \x01(\x05\x12\x12\n\ntrace_name\x18\x02 \x01(\t\x12\x13\n\x0btrace_begin\x18\x03 \x01(\r\x12\x12\n\ntrace_type\x18\x04 \x01(\r\x12\r\n\x05value\x18\x05 \x01(\x05"\x9c\x01\n\x16SchedSwitchFtraceEvent\x12\x11\n\tprev_comm\x18\x01 \x01(\t\x12\x10\n\x08prev_pid\x18\x02 \x01(\x05\x12\x11\n\tprev_prio\x18\x03 \x01(\x05\x12\x12\n\nprev_state\x18\x04 \x01(\x03\x12\x11\n\tnext_comm\x18\x05 \x01(\t\x12\x10\n\x08next_pid\x18\x06 \x01(\x05\x12\x11\n\tnext_prio\x18\x07 \x01(\x05"f\n\x16SchedWakeupFtraceEvent\x12\x0c\n\x04\x63omm\x18\x01 \x01(\t\x12\x0b\n\x03pid\x18\x02 \x01(\x05\x12\x0c\n\x04prio\x18\x03 \x01(\x05\x12\x0f\n\x07success\x18\x04 \x01(\x05\x12\x12\n\ntarget_cpu\x18\x05 \x01(\x05"M\n\x1dSchedBlockedReasonFtraceEvent\x12\x0b\n\x03pid\x18\x01 \x01(\x05\x12\x0e\n\x06\x63\x61ller\x18\x02 \x01(\x04\x12\x0f\n\x07io_wait\x18\x03 \x01(\r"Q\n\x1aSchedCpuHotplugFtraceEvent\x12\x14\n\x0c\x61\x66\x66\x65\x63ted_cpu\x18\x01 \x01(\x05\x12\r\n\x05\x65rror\x18\x02 \x01(\x05\x12\x0e\n\x06status\x18\x03 \x01(\x05"f\n\x16SchedWakingFtraceEvent\x12\x0c\n\x04\x63omm\x18\x01 \x01(\t\x12\x0b\n\x03pid\x18\x02 \x01(\x05\x12\x0c\n\x04prio\x18\x03 \x01(\x05\x12\x0f\n\x07success\x18\x04 \x01(\x05\x12\x12\n\ntarget_cpu\x18\x05 \x01(\x05"i\n\x19SchedWakeupNewFtraceEvent\x12\x0c\n\x04\x63omm\x18\x01 \x01(\t\x12\x0b\n\x03pid\x18\x02 \x01(\x05\x12\x0c\n\x04prio\x18\x03 \x01(\x05\x12\x0f\n\x07success\x18\x04 \x01(\x05\x12\x12\n\ntarget_cpu\x18\x05 \x01(\x05"M\n\x1bSchedProcessExecFtraceEvent\x12\x10\n\x08\x66ilename\x18\x01 \x01(\t\x12\x0b\n\x03pid\x18\x02 \x01(\x05\x12\x0f\n\x07old_pid\x18\x03 \x01(\x05"T\n\x1bSchedProcessExitFtraceEvent\x12\x0c\n\x04\x63omm\x18\x01 \x01(\t\x12\x0b\n\x03pid\x18\x02 \x01(\x05\x12\x0c\n\x04tgid\x18\x03 \x01(\x05\x12\x0c\n\x04prio\x18\x04 \x01(\x05"m\n\x1bSchedProcessForkFtraceEvent\x12\x13\n\x0bparent_comm\x18\x01 \x01(\t\x12\x12\n\nparent_pid\x18\x02 \x01(\x05\x12\x12\n\nchild_comm\x18\x03 \x01(\t\x12\x11\n\tchild_pid\x18\x04 \x01(\x05"F\n\x1bSchedProcessFreeFtraceEvent\x12\x0c\n\x04\x63omm\x18\x01 \x01(\t\x12\x0b\n\x03pid\x18\x02 \x01(\x05\x12\x0c\n\x04prio\x18\x03 \x01(\x05"8\n\x1bSchedProcessHangFtraceEvent\x12\x0c\n\x04\x63omm\x18\x01 \x01(\t\x12\x0b\n\x03pid\x18\x02 \x01(\x05"F\n\x1bSchedProcessWaitFtraceEvent\x12\x0c\n\x04\x63omm\x18\x01 \x01(\t\x12\x0b\n\x03pid\x18\x02 \x01(\x05\x12\x0c\n\x04prio\x18\x03 \x01(\x05"X\n\x19SchedPiSetprioFtraceEvent\x12\x0c\n\x04\x63omm\x18\x01 \x01(\t\x12\x0f\n\x07newprio\x18\x02 \x01(\x05\x12\x0f\n\x07oldprio\x18\x03 \x01(\x05\x12\x0b\n\x03pid\x18\x04 \x01(\x05"\xc8\x02\n\x1aSchedCpuUtilCfsFtraceEvent\x12\x0e\n\x06\x61\x63tive\x18\x01 \x01(\x05\x12\x10\n\x08\x63\x61pacity\x18\x02 \x01(\x04\x12\x15\n\rcapacity_orig\x18\x03 \x01(\x04\x12\x0b\n\x03\x63pu\x18\x04 \x01(\r\x12\x16\n\x0e\x63pu_importance\x18\x05 \x01(\x04\x12\x10\n\x08\x63pu_util\x18\x06 \x01(\x04\x12\x10\n\x08\x65xit_lat\x18\x07 \x01(\r\x12\x16\n\x0egroup_capacity\x18\x08 \x01(\x04\x12\x18\n\x10grp_overutilized\x18\t \x01(\r\x12\x10\n\x08idle_cpu\x18\n \x01(\r\x12\x12\n\nnr_running\x18\x0b \x01(\r\x12\x11\n\tspare_cap\x18\x0c \x01(\x03\x12\x11\n\ttask_fits\x18\r \x01(\r\x12\x17\n\x0fwake_group_util\x18\x0e \x01(\x04\x12\x11\n\twake_util\x18\x0f \x01(\x04"\x89\x01\n\x1bSchedMigrateTaskFtraceEvent\x12\x0c\n\x04\x63omm\x18\x01 \x01(\t\x12\x0b\n\x03pid\x18\x02 \x01(\x05\x12\x0c\n\x04prio\x18\x03 \x01(\x05\x12\x10\n\x08orig_cpu\x18\x04 \x01(\x05\x12\x10\n\x08\x64\x65st_cpu\x18\x05 \x01(\x05\x12\x0f\n\x07running\x18\x06 \x01(\x05\x12\x0c\n\x04load\x18\x07 \x01(\r"|\n\x1eSchedWakeupTaskAttrFtraceEvent\x12\x0b\n\x03pid\x18\x01 \x01(\x05\x12\x14\n\x0c\x63pu_affinity\x18\x02 \x01(\x04\x12\x11\n\ttask_util\x18\x03 \x01(\x04\x12\x12\n\nuclamp_min\x18\x04 \x01(\x04\x12\x10\n\x08vruntime\x18\x05 \x01(\x04"B\n\x17ScmCallStartFtraceEvent\x12\x0f\n\x07\x61rginfo\x18\x01 \x01(\r\x12\n\n\x02x0\x18\x02 \x01(\x04\x12\n\n\x02x5\x18\x03 \x01(\x04"\x17\n\x15ScmCallEndFtraceEvent"y\n\x1eSdeTracingMarkWriteFtraceEvent\x12\x0b\n\x03pid\x18\x01 \x01(\x05\x12\x12\n\ntrace_name\x18\x02 \x01(\t\x12\x12\n\ntrace_type\x18\x03 \x01(\r\x12\r\n\x05value\x18\x04 \x01(\x05\x12\x13\n\x0btrace_begin\x18\x05 \x01(\r"J\n\x17SdeSdeEvtlogFtraceEvent\x12\x12\n\nevtlog_tag\x18\x01 \x01(\t\x12\x0b\n\x03pid\x18\x02 \x01(\x05\x12\x0e\n\x06tag_id\x18\x03 \x01(\r"\xb4\x01\n\x1dSdeSdePerfCalcCrtcFtraceEvent\x12\x12\n\nbw_ctl_ebi\x18\x01 \x01(\x04\x12\x13\n\x0b\x62w_ctl_llcc\x18\x02 \x01(\x04\x12\x13\n\x0b\x62w_ctl_mnoc\x18\x03 \x01(\x04\x12\x15\n\rcore_clk_rate\x18\x04 \x01(\r\x12\x0c\n\x04\x63rtc\x18\x05 \x01(\r\x12\x0e\n\x06ib_ebi\x18\x06 \x01(\x04\x12\x0f\n\x07ib_llcc\x18\x07 \x01(\x04\x12\x0f\n\x07ib_mnoc\x18\x08 \x01(\x04"\x9b\x02\n\x1fSdeSdePerfCrtcUpdateFtraceEvent\x12\x12\n\nbw_ctl_ebi\x18\x01 \x01(\x04\x12\x13\n\x0b\x62w_ctl_llcc\x18\x02 \x01(\x04\x12\x13\n\x0b\x62w_ctl_mnoc\x18\x03 \x01(\x04\x12\x15\n\rcore_clk_rate\x18\x04 \x01(\r\x12\x0c\n\x04\x63rtc\x18\x05 \x01(\r\x12\x0e\n\x06params\x18\x06 \x01(\x05\x12\x17\n\x0fper_pipe_ib_ebi\x18\x07 \x01(\x04\x12\x18\n\x10per_pipe_ib_llcc\x18\x08 \x01(\x04\x12\x18\n\x10per_pipe_ib_mnoc\x18\t \x01(\x04\x12\x10\n\x08stop_req\x18\n \x01(\r\x12\x12\n\nupdate_bus\x18\x0b \x01(\r\x12\x12\n\nupdate_clk\x18\x0c \x01(\r"t\n\x1fSdeSdePerfSetQosLutsFtraceEvent\x12\n\n\x02\x66l\x18\x01 \x01(\r\x12\x0b\n\x03\x66mt\x18\x02 \x01(\r\x12\x0b\n\x03lut\x18\x03 \x01(\x04\x12\x11\n\tlut_usage\x18\x04 \x01(\r\x12\x0c\n\x04pnum\x18\x05 \x01(\r\x12\n\n\x02rt\x18\x06 \x01(\r"d\n\x1eSdeSdePerfUpdateBusFtraceEvent\x12\x10\n\x08\x61\x62_quota\x18\x01 \x01(\x04\x12\x0e\n\x06\x62us_id\x18\x02 \x01(\r\x12\x0e\n\x06\x63lient\x18\x03 \x01(\x05\x12\x10\n\x08ib_quota\x18\x04 \x01(\x04"G\n\x18SignalDeliverFtraceEvent\x12\x0c\n\x04\x63ode\x18\x01 \x01(\x05\x12\x10\n\x08sa_flags\x18\x02 \x01(\x04\x12\x0b\n\x03sig\x18\x03 \x01(\x05"p\n\x19SignalGenerateFtraceEvent\x12\x0c\n\x04\x63ode\x18\x01 \x01(\x05\x12\x0c\n\x04\x63omm\x18\x02 \x01(\t\x12\r\n\x05group\x18\x03 \x01(\x05\x12\x0b\n\x03pid\x18\x04 \x01(\x05\x12\x0e\n\x06result\x18\x05 \x01(\x05\x12\x0b\n\x03sig\x18\x06 \x01(\x05"J\n\x13KfreeSkbFtraceEvent\x12\x10\n\x08location\x18\x01 \x01(\x04\x12\x10\n\x08protocol\x18\x02 \x01(\r\x12\x0f\n\x07skbaddr\x18\x03 \x01(\x04"\xaf\x01\n\x1bInetSockSetStateFtraceEvent\x12\r\n\x05\x64\x61\x64\x64r\x18\x01 \x01(\r\x12\r\n\x05\x64port\x18\x02 \x01(\r\x12\x0e\n\x06\x66\x61mily\x18\x03 \x01(\r\x12\x10\n\x08newstate\x18\x04 \x01(\x05\x12\x10\n\x08oldstate\x18\x05 \x01(\x05\x12\x10\n\x08protocol\x18\x06 \x01(\r\x12\r\n\x05saddr\x18\x07 \x01(\r\x12\x0e\n\x06skaddr\x18\x08 \x01(\x04\x12\r\n\x05sport\x18\t \x01(\r"4\n\x11SyncPtFtraceEvent\x12\x10\n\x08timeline\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t"6\n\x17SyncTimelineFtraceEvent\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t"B\n\x13SyncWaitFtraceEvent\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x0e\n\x06status\x18\x02 \x01(\x05\x12\r\n\x05\x62\x65gin\x18\x03 \x01(\r"X\n\x1bRssStatThrottledFtraceEvent\x12\x0c\n\x04\x63urr\x18\x01 \x01(\r\x12\x0e\n\x06member\x18\x02 \x01(\x05\x12\r\n\x05mm_id\x18\x03 \x01(\r\x12\x0c\n\x04size\x18\x04 \x01(\x03"0\n\x1fSuspendResumeMinimalFtraceEvent\x12\r\n\x05start\x18\x01 \x01(\r"I\n\x0fZeroFtraceEvent\x12\x0c\n\x04\x66lag\x18\x01 \x01(\x05\x12\x0c\n\x04name\x18\x02 \x01(\t\x12\x0b\n\x03pid\x18\x03 \x01(\x05\x12\r\n\x05value\x18\x04 \x01(\x03"_\n\x16TaskNewtaskFtraceEvent\x12\x0b\n\x03pid\x18\x01 \x01(\x05\x12\x0c\n\x04\x63omm\x18\x02 \x01(\t\x12\x13\n\x0b\x63lone_flags\x18\x03 \x01(\x04\x12\x15\n\room_score_adj\x18\x04 \x01(\x05"]\n\x15TaskRenameFtraceEvent\x12\x0b\n\x03pid\x18\x01 \x01(\x05\x12\x0f\n\x07oldcomm\x18\x02 \x01(\t\x12\x0f\n\x07newcomm\x18\x03 \x01(\t\x12\x15\n\room_score_adj\x18\x04 \x01(\x05"\x89\x01\n\x1bTcpRetransmitSkbFtraceEvent\x12\r\n\x05\x64\x61\x64\x64r\x18\x01 \x01(\r\x12\r\n\x05\x64port\x18\x02 \x01(\r\x12\r\n\x05saddr\x18\x03 \x01(\r\x12\x0e\n\x06skaddr\x18\x04 \x01(\x04\x12\x0f\n\x07skbaddr\x18\x05 \x01(\x04\x12\r\n\x05sport\x18\x06 \x01(\r\x12\r\n\x05state\x18\x07 \x01(\x05"b\n\x1dThermalTemperatureFtraceEvent\x12\n\n\x02id\x18\x01 \x01(\x05\x12\x0c\n\x04temp\x18\x02 \x01(\x05\x12\x11\n\ttemp_prev\x18\x03 \x01(\x05\x12\x14\n\x0cthermal_zone\x18\x04 \x01(\t"5\n\x15\x43\x64\x65vUpdateFtraceEvent\x12\x0e\n\x06target\x18\x01 \x01(\x04\x12\x0c\n\x04type\x18\x02 \x01(\t"\xe4\x01\n ThermalExynosAcpmBulkFtraceEvent\x12\r\n\x05tz_id\x18\x01 \x01(\r\x12\x14\n\x0c\x63urrent_temp\x18\x02 \x01(\r\x12\x11\n\tctrl_temp\x18\x03 \x01(\r\x12\x12\n\ncdev_state\x18\x04 \x01(\r\x12\x10\n\x08pid_et_p\x18\x05 \x01(\x05\x12\x17\n\x0fpid_power_range\x18\x06 \x01(\x05\x12\r\n\x05pid_p\x18\x07 \x01(\x05\x12\r\n\x05pid_i\x18\x08 \x01(\x05\x12\x0b\n\x03k_p\x18\t \x01(\x05\x12\x0b\n\x03k_i\x18\n \x01(\x05\x12\x11\n\ttimestamp\x18\x0b \x01(\x04"\xa2\x01\n(ThermalExynosAcpmHighOverheadFtraceEvent\x12\r\n\x05tz_id\x18\x01 \x01(\x05\x12\x14\n\x0c\x63urrent_temp\x18\x02 \x01(\r\x12\x11\n\tctrl_temp\x18\x03 \x01(\r\x12\x12\n\ncdev_state\x18\x04 \x01(\r\x12\x10\n\x08pid_et_p\x18\x05 \x01(\x05\x12\x0b\n\x03k_p\x18\x06 \x01(\x05\x12\x0b\n\x03k_i\x18\x07 \x01(\x05"F\n\x14TrustySmcFtraceEvent\x12\n\n\x02r0\x18\x01 \x01(\x04\x12\n\n\x02r1\x18\x02 \x01(\x04\x12\n\n\x02r2\x18\x03 \x01(\x04\x12\n\n\x02r3\x18\x04 \x01(\x04"\'\n\x18TrustySmcDoneFtraceEvent\x12\x0b\n\x03ret\x18\x01 \x01(\x04"L\n\x1aTrustyStdCall32FtraceEvent\x12\n\n\x02r0\x18\x01 \x01(\x04\x12\n\n\x02r1\x18\x02 \x01(\x04\x12\n\n\x02r2\x18\x03 \x01(\x04\x12\n\n\x02r3\x18\x04 \x01(\x04"-\n\x1eTrustyStdCall32DoneFtraceEvent\x12\x0b\n\x03ret\x18\x01 \x01(\x03"H\n\x1cTrustyShareMemoryFtraceEvent\x12\x0b\n\x03len\x18\x01 \x01(\x04\x12\x0c\n\x04lend\x18\x02 \x01(\r\x12\r\n\x05nents\x18\x03 \x01(\r"i\n TrustyShareMemoryDoneFtraceEvent\x12\x0e\n\x06handle\x18\x01 \x01(\x04\x12\x0b\n\x03len\x18\x02 \x01(\x04\x12\x0c\n\x04lend\x18\x03 \x01(\r\x12\r\n\x05nents\x18\x04 \x01(\r\x12\x0b\n\x03ret\x18\x05 \x01(\x05",\n\x1eTrustyReclaimMemoryFtraceEvent\x12\n\n\x02id\x18\x01 \x01(\x04"=\n"TrustyReclaimMemoryDoneFtraceEvent\x12\n\n\x02id\x18\x01 \x01(\x04\x12\x0b\n\x03ret\x18\x02 \x01(\x05"#\n\x14TrustyIrqFtraceEvent\x12\x0b\n\x03irq\x18\x01 \x01(\x05"S\n\x1fTrustyIpcHandleEventFtraceEvent\x12\x0c\n\x04\x63han\x18\x01 \x01(\r\x12\x10\n\x08\x65vent_id\x18\x02 \x01(\r\x12\x10\n\x08srv_name\x18\x03 \x01(\t"H\n\x1bTrustyIpcConnectFtraceEvent\x12\x0c\n\x04\x63han\x18\x01 \x01(\r\x12\x0c\n\x04port\x18\x02 \x01(\t\x12\r\n\x05state\x18\x03 \x01(\x05"J\n\x1eTrustyIpcConnectEndFtraceEvent\x12\x0c\n\x04\x63han\x18\x01 \x01(\r\x12\x0b\n\x03\x65rr\x18\x02 \x01(\x05\x12\r\n\x05state\x18\x03 \x01(\x05"\x82\x01\n\x19TrustyIpcWriteFtraceEvent\x12\x0e\n\x06\x62uf_id\x18\x01 \x01(\x04\x12\x0c\n\x04\x63han\x18\x02 \x01(\r\x12\x10\n\x08kind_shm\x18\x03 \x01(\x05\x12\x12\n\nlen_or_err\x18\x04 \x01(\x05\x12\x0f\n\x07shm_cnt\x18\x05 \x01(\x04\x12\x10\n\x08srv_name\x18\x06 \x01(\t"M\n\x18TrustyIpcPollFtraceEvent\x12\x0c\n\x04\x63han\x18\x01 \x01(\r\x12\x11\n\tpoll_mask\x18\x02 \x01(\r\x12\x10\n\x08srv_name\x18\x03 \x01(\t":\n\x18TrustyIpcReadFtraceEvent\x12\x0c\n\x04\x63han\x18\x01 \x01(\r\x12\x10\n\x08srv_name\x18\x02 \x01(\t"r\n\x1bTrustyIpcReadEndFtraceEvent\x12\x0e\n\x06\x62uf_id\x18\x01 \x01(\x04\x12\x0c\n\x04\x63han\x18\x02 \x01(\r\x12\x12\n\nlen_or_err\x18\x03 \x01(\x05\x12\x0f\n\x07shm_cnt\x18\x04 \x01(\x04\x12\x10\n\x08srv_name\x18\x05 \x01(\t"H\n\x16TrustyIpcRxFtraceEvent\x12\x0e\n\x06\x62uf_id\x18\x01 \x01(\x04\x12\x0c\n\x04\x63han\x18\x02 \x01(\r\x12\x10\n\x08srv_name\x18\x03 \x01(\t"G\n\x1bTrustyEnqueueNopFtraceEvent\x12\x0c\n\x04\x61rg1\x18\x01 \x01(\r\x12\x0c\n\x04\x61rg2\x18\x02 \x01(\r\x12\x0c\n\x04\x61rg3\x18\x03 \x01(\r"\xba\x01\n\x18UfshcdCommandFtraceEvent\x12\x10\n\x08\x64\x65v_name\x18\x01 \x01(\t\x12\x10\n\x08\x64oorbell\x18\x02 \x01(\r\x12\x0c\n\x04intr\x18\x03 \x01(\r\x12\x0b\n\x03lba\x18\x04 \x01(\x04\x12\x0e\n\x06opcode\x18\x05 \x01(\r\x12\x0b\n\x03str\x18\x06 \x01(\t\x12\x0b\n\x03tag\x18\x07 \x01(\r\x12\x14\n\x0ctransfer_len\x18\x08 \x01(\x05\x12\x10\n\x08group_id\x18\t \x01(\r\x12\r\n\x05str_t\x18\n \x01(\r"=\n\x1aUfshcdClkGatingFtraceEvent\x12\x10\n\x08\x64\x65v_name\x18\x01 \x01(\t\x12\r\n\x05state\x18\x02 \x01(\x05"\x9b\x03\n\x13V4l2QbufFtraceEvent\x12\x11\n\tbytesused\x18\x01 \x01(\r\x12\r\n\x05\x66ield\x18\x02 \x01(\r\x12\r\n\x05\x66lags\x18\x03 \x01(\r\x12\r\n\x05index\x18\x04 \x01(\r\x12\r\n\x05minor\x18\x05 \x01(\x05\x12\x10\n\x08sequence\x18\x06 \x01(\r\x12\x16\n\x0etimecode_flags\x18\x07 \x01(\r\x12\x17\n\x0ftimecode_frames\x18\x08 \x01(\r\x12\x16\n\x0etimecode_hours\x18\t \x01(\r\x12\x18\n\x10timecode_minutes\x18\n \x01(\r\x12\x18\n\x10timecode_seconds\x18\x0b \x01(\r\x12\x15\n\rtimecode_type\x18\x0c \x01(\r\x12\x1a\n\x12timecode_userbits0\x18\r \x01(\r\x12\x1a\n\x12timecode_userbits1\x18\x0e \x01(\r\x12\x1a\n\x12timecode_userbits2\x18\x0f \x01(\r\x12\x1a\n\x12timecode_userbits3\x18\x10 \x01(\r\x12\x11\n\ttimestamp\x18\x11 \x01(\x03\x12\x0c\n\x04type\x18\x12 \x01(\r"\x9c\x03\n\x14V4l2DqbufFtraceEvent\x12\x11\n\tbytesused\x18\x01 \x01(\r\x12\r\n\x05\x66ield\x18\x02 \x01(\r\x12\r\n\x05\x66lags\x18\x03 \x01(\r\x12\r\n\x05index\x18\x04 \x01(\r\x12\r\n\x05minor\x18\x05 \x01(\x05\x12\x10\n\x08sequence\x18\x06 \x01(\r\x12\x16\n\x0etimecode_flags\x18\x07 \x01(\r\x12\x17\n\x0ftimecode_frames\x18\x08 \x01(\r\x12\x16\n\x0etimecode_hours\x18\t \x01(\r\x12\x18\n\x10timecode_minutes\x18\n \x01(\r\x12\x18\n\x10timecode_seconds\x18\x0b \x01(\r\x12\x15\n\rtimecode_type\x18\x0c \x01(\r\x12\x1a\n\x12timecode_userbits0\x18\r \x01(\r\x12\x1a\n\x12timecode_userbits1\x18\x0e \x01(\r\x12\x1a\n\x12timecode_userbits2\x18\x0f \x01(\r\x12\x1a\n\x12timecode_userbits3\x18\x10 \x01(\r\x12\x11\n\ttimestamp\x18\x11 \x01(\x03\x12\x0c\n\x04type\x18\x12 \x01(\r"\xf2\x02\n\x1aVb2V4l2BufQueueFtraceEvent\x12\r\n\x05\x66ield\x18\x01 \x01(\r\x12\r\n\x05\x66lags\x18\x02 \x01(\r\x12\r\n\x05minor\x18\x03 \x01(\x05\x12\x10\n\x08sequence\x18\x04 \x01(\r\x12\x16\n\x0etimecode_flags\x18\x05 \x01(\r\x12\x17\n\x0ftimecode_frames\x18\x06 \x01(\r\x12\x16\n\x0etimecode_hours\x18\x07 \x01(\r\x12\x18\n\x10timecode_minutes\x18\x08 \x01(\r\x12\x18\n\x10timecode_seconds\x18\t \x01(\r\x12\x15\n\rtimecode_type\x18\n \x01(\r\x12\x1a\n\x12timecode_userbits0\x18\x0b \x01(\r\x12\x1a\n\x12timecode_userbits1\x18\x0c \x01(\r\x12\x1a\n\x12timecode_userbits2\x18\r \x01(\r\x12\x1a\n\x12timecode_userbits3\x18\x0e \x01(\r\x12\x11\n\ttimestamp\x18\x0f \x01(\x03"\xf1\x02\n\x19Vb2V4l2BufDoneFtraceEvent\x12\r\n\x05\x66ield\x18\x01 \x01(\r\x12\r\n\x05\x66lags\x18\x02 \x01(\r\x12\r\n\x05minor\x18\x03 \x01(\x05\x12\x10\n\x08sequence\x18\x04 \x01(\r\x12\x16\n\x0etimecode_flags\x18\x05 \x01(\r\x12\x17\n\x0ftimecode_frames\x18\x06 \x01(\r\x12\x16\n\x0etimecode_hours\x18\x07 \x01(\r\x12\x18\n\x10timecode_minutes\x18\x08 \x01(\r\x12\x18\n\x10timecode_seconds\x18\t \x01(\r\x12\x15\n\rtimecode_type\x18\n \x01(\r\x12\x1a\n\x12timecode_userbits0\x18\x0b \x01(\r\x12\x1a\n\x12timecode_userbits1\x18\x0c \x01(\r\x12\x1a\n\x12timecode_userbits2\x18\r \x01(\r\x12\x1a\n\x12timecode_userbits3\x18\x0e \x01(\r\x12\x11\n\ttimestamp\x18\x0f \x01(\x03"\xee\x02\n\x16Vb2V4l2QbufFtraceEvent\x12\r\n\x05\x66ield\x18\x01 \x01(\r\x12\r\n\x05\x66lags\x18\x02 \x01(\r\x12\r\n\x05minor\x18\x03 \x01(\x05\x12\x10\n\x08sequence\x18\x04 \x01(\r\x12\x16\n\x0etimecode_flags\x18\x05 \x01(\r\x12\x17\n\x0ftimecode_frames\x18\x06 \x01(\r\x12\x16\n\x0etimecode_hours\x18\x07 \x01(\r\x12\x18\n\x10timecode_minutes\x18\x08 \x01(\r\x12\x18\n\x10timecode_seconds\x18\t \x01(\r\x12\x15\n\rtimecode_type\x18\n \x01(\r\x12\x1a\n\x12timecode_userbits0\x18\x0b \x01(\r\x12\x1a\n\x12timecode_userbits1\x18\x0c \x01(\r\x12\x1a\n\x12timecode_userbits2\x18\r \x01(\r\x12\x1a\n\x12timecode_userbits3\x18\x0e \x01(\r\x12\x11\n\ttimestamp\x18\x0f \x01(\x03"\xef\x02\n\x17Vb2V4l2DqbufFtraceEvent\x12\r\n\x05\x66ield\x18\x01 \x01(\r\x12\r\n\x05\x66lags\x18\x02 \x01(\r\x12\r\n\x05minor\x18\x03 \x01(\x05\x12\x10\n\x08sequence\x18\x04 \x01(\r\x12\x16\n\x0etimecode_flags\x18\x05 \x01(\r\x12\x17\n\x0ftimecode_frames\x18\x06 \x01(\r\x12\x16\n\x0etimecode_hours\x18\x07 \x01(\r\x12\x18\n\x10timecode_minutes\x18\x08 \x01(\r\x12\x18\n\x10timecode_seconds\x18\t \x01(\r\x12\x15\n\rtimecode_type\x18\n \x01(\r\x12\x1a\n\x12timecode_userbits0\x18\x0b \x01(\r\x12\x1a\n\x12timecode_userbits1\x18\x0c \x01(\r\x12\x1a\n\x12timecode_userbits2\x18\r \x01(\r\x12\x1a\n\x12timecode_userbits3\x18\x0e \x01(\r\x12\x11\n\ttimestamp\x18\x0f \x01(\x03"\xa5\x01\n\x1cVirtioGpuCmdQueueFtraceEvent\x12\x0e\n\x06\x63tx_id\x18\x01 \x01(\r\x12\x0b\n\x03\x64\x65v\x18\x02 \x01(\x05\x12\x10\n\x08\x66\x65nce_id\x18\x03 \x01(\x04\x12\r\n\x05\x66lags\x18\x04 \x01(\r\x12\x0c\n\x04name\x18\x05 \x01(\t\x12\x10\n\x08num_free\x18\x06 \x01(\r\x12\r\n\x05seqno\x18\x07 \x01(\r\x12\x0c\n\x04type\x18\x08 \x01(\r\x12\n\n\x02vq\x18\t \x01(\r"\xa8\x01\n\x1fVirtioGpuCmdResponseFtraceEvent\x12\x0e\n\x06\x63tx_id\x18\x01 \x01(\r\x12\x0b\n\x03\x64\x65v\x18\x02 \x01(\x05\x12\x10\n\x08\x66\x65nce_id\x18\x03 \x01(\x04\x12\r\n\x05\x66lags\x18\x04 \x01(\r\x12\x0c\n\x04name\x18\x05 \x01(\t\x12\x10\n\x08num_free\x18\x06 \x01(\r\x12\r\n\x05seqno\x18\x07 \x01(\r\x12\x0c\n\x04type\x18\x08 \x01(\r\x12\n\n\x02vq\x18\t \x01(\r"<\n\x19VirtioVideoCmdFtraceEvent\x12\x11\n\tstream_id\x18\x01 \x01(\r\x12\x0c\n\x04type\x18\x02 \x01(\r"@\n\x1dVirtioVideoCmdDoneFtraceEvent\x12\x11\n\tstream_id\x18\x01 \x01(\r\x12\x0c\n\x04type\x18\x02 \x01(\r"\xc4\x01\n#VirtioVideoResourceQueueFtraceEvent\x12\x12\n\ndata_size0\x18\x01 \x01(\r\x12\x12\n\ndata_size1\x18\x02 \x01(\r\x12\x12\n\ndata_size2\x18\x03 \x01(\r\x12\x12\n\ndata_size3\x18\x04 \x01(\r\x12\x12\n\nqueue_type\x18\x05 \x01(\r\x12\x13\n\x0bresource_id\x18\x06 \x01(\x05\x12\x11\n\tstream_id\x18\x07 \x01(\x05\x12\x11\n\ttimestamp\x18\x08 \x01(\x04"\xc8\x01\n\'VirtioVideoResourceQueueDoneFtraceEvent\x12\x12\n\ndata_size0\x18\x01 \x01(\r\x12\x12\n\ndata_size1\x18\x02 \x01(\r\x12\x12\n\ndata_size2\x18\x03 \x01(\r\x12\x12\n\ndata_size3\x18\x04 \x01(\r\x12\x12\n\nqueue_type\x18\x05 \x01(\r\x12\x13\n\x0bresource_id\x18\x06 \x01(\x05\x12\x11\n\tstream_id\x18\x07 \x01(\x05\x12\x11\n\ttimestamp\x18\x08 \x01(\x04"`\n%MmVmscanDirectReclaimBeginFtraceEvent\x12\r\n\x05order\x18\x01 \x01(\x05\x12\x15\n\rmay_writepage\x18\x02 \x01(\x05\x12\x11\n\tgfp_flags\x18\x03 \x01(\r";\n#MmVmscanDirectReclaimEndFtraceEvent\x12\x14\n\x0cnr_reclaimed\x18\x01 \x01(\x04"H\n\x1dMmVmscanKswapdWakeFtraceEvent\x12\x0b\n\x03nid\x18\x01 \x01(\x05\x12\r\n\x05order\x18\x02 \x01(\x05\x12\x0b\n\x03zid\x18\x03 \x01(\x05"-\n\x1eMmVmscanKswapdSleepFtraceEvent\x12\x0b\n\x03nid\x18\x01 \x01(\x05"\xe9\x01\n\x1cMmShrinkSlabStartFtraceEvent\x12\x13\n\x0b\x63\x61\x63he_items\x18\x01 \x01(\x04\x12\r\n\x05\x64\x65lta\x18\x02 \x01(\x04\x12\x11\n\tgfp_flags\x18\x03 \x01(\r\x12\x0f\n\x07lru_pgs\x18\x04 \x01(\x04\x12\x1c\n\x14nr_objects_to_shrink\x18\x05 \x01(\x03\x12\x13\n\x0bpgs_scanned\x18\x06 \x01(\x04\x12\x0b\n\x03shr\x18\x07 \x01(\x04\x12\x0e\n\x06shrink\x18\x08 \x01(\x04\x12\x12\n\ntotal_scan\x18\t \x01(\x04\x12\x0b\n\x03nid\x18\n \x01(\x05\x12\x10\n\x08priority\x18\x0b \x01(\x05"\x91\x01\n\x1aMmShrinkSlabEndFtraceEvent\x12\x10\n\x08new_scan\x18\x01 \x01(\x03\x12\x0e\n\x06retval\x18\x02 \x01(\x05\x12\x0b\n\x03shr\x18\x03 \x01(\x04\x12\x0e\n\x06shrink\x18\x04 \x01(\x04\x12\x12\n\ntotal_scan\x18\x05 \x01(\x03\x12\x13\n\x0bunused_scan\x18\x06 \x01(\x03\x12\x0b\n\x03nid\x18\x07 \x01(\x05"0\n WorkqueueActivateWorkFtraceEvent\x12\x0c\n\x04work\x18\x01 \x01(\x04"@\n\x1eWorkqueueExecuteEndFtraceEvent\x12\x0c\n\x04work\x18\x01 \x01(\x04\x12\x10\n\x08\x66unction\x18\x02 \x01(\x04"B\n WorkqueueExecuteStartFtraceEvent\x12\x0c\n\x04work\x18\x01 \x01(\x04\x12\x10\n\x08\x66unction\x18\x02 \x01(\x04"p\n\x1dWorkqueueQueueWorkFtraceEvent\x12\x0c\n\x04work\x18\x01 \x01(\x04\x12\x10\n\x08\x66unction\x18\x02 \x01(\x04\x12\x11\n\tworkqueue\x18\x03 \x01(\x04\x12\x0f\n\x07req_cpu\x18\x04 \x01(\r\x12\x0b\n\x03\x63pu\x18\x05 \x01(\r"\xf8\xbd\x02\n\x0b\x46traceEvent\x12\x11\n\ttimestamp\x18\x01 \x01(\x04\x12\x0b\n\x03pid\x18\x02 \x01(\r\x12\x14\n\x0c\x63ommon_flags\x18\x05 \x01(\r\x12\x32\n\x05print\x18\x03 \x01(\x0b\x32!.perfetto.protos.PrintFtraceEventH\x00\x12?\n\x0csched_switch\x18\x04 \x01(\x0b\x32\'.perfetto.protos.SchedSwitchFtraceEventH\x00\x12\x41\n\rcpu_frequency\x18\x0b \x01(\x0b\x32(.perfetto.protos.CpuFrequencyFtraceEventH\x00\x12N\n\x14\x63pu_frequency_limits\x18\x0c \x01(\x0b\x32..perfetto.protos.CpuFrequencyLimitsFtraceEventH\x00\x12\x37\n\x08\x63pu_idle\x18\r \x01(\x0b\x32#.perfetto.protos.CpuIdleFtraceEventH\x00\x12?\n\x0c\x63lock_enable\x18\x0e \x01(\x0b\x32\'.perfetto.protos.ClockEnableFtraceEventH\x00\x12\x41\n\rclock_disable\x18\x0f \x01(\x0b\x32(.perfetto.protos.ClockDisableFtraceEventH\x00\x12\x42\n\x0e\x63lock_set_rate\x18\x10 \x01(\x0b\x32(.perfetto.protos.ClockSetRateFtraceEventH\x00\x12?\n\x0csched_wakeup\x18\x11 \x01(\x0b\x32\'.perfetto.protos.SchedWakeupFtraceEventH\x00\x12N\n\x14sched_blocked_reason\x18\x12 \x01(\x0b\x32..perfetto.protos.SchedBlockedReasonFtraceEventH\x00\x12H\n\x11sched_cpu_hotplug\x18\x13 \x01(\x0b\x32+.perfetto.protos.SchedCpuHotplugFtraceEventH\x00\x12?\n\x0csched_waking\x18\x14 \x01(\x0b\x32\'.perfetto.protos.SchedWakingFtraceEventH\x00\x12\x39\n\tipi_entry\x18\x15 \x01(\x0b\x32$.perfetto.protos.IpiEntryFtraceEventH\x00\x12\x37\n\x08ipi_exit\x18\x16 \x01(\x0b\x32#.perfetto.protos.IpiExitFtraceEventH\x00\x12\x39\n\tipi_raise\x18\x17 \x01(\x0b\x32$.perfetto.protos.IpiRaiseFtraceEventH\x00\x12\x41\n\rsoftirq_entry\x18\x18 \x01(\x0b\x32(.perfetto.protos.SoftirqEntryFtraceEventH\x00\x12?\n\x0csoftirq_exit\x18\x19 \x01(\x0b\x32\'.perfetto.protos.SoftirqExitFtraceEventH\x00\x12\x41\n\rsoftirq_raise\x18\x1a \x01(\x0b\x32(.perfetto.protos.SoftirqRaiseFtraceEventH\x00\x12\x37\n\x08i2c_read\x18\x1b \x01(\x0b\x32#.perfetto.protos.I2cReadFtraceEventH\x00\x12\x39\n\ti2c_write\x18\x1c \x01(\x0b\x32$.perfetto.protos.I2cWriteFtraceEventH\x00\x12;\n\ni2c_result\x18\x1d \x01(\x0b\x32%.perfetto.protos.I2cResultFtraceEventH\x00\x12\x39\n\ti2c_reply\x18\x1e \x01(\x0b\x32$.perfetto.protos.I2cReplyFtraceEventH\x00\x12;\n\nsmbus_read\x18\x1f \x01(\x0b\x32%.perfetto.protos.SmbusReadFtraceEventH\x00\x12=\n\x0bsmbus_write\x18 \x01(\x0b\x32&.perfetto.protos.SmbusWriteFtraceEventH\x00\x12?\n\x0csmbus_result\x18! \x01(\x0b\x32\'.perfetto.protos.SmbusResultFtraceEventH\x00\x12=\n\x0bsmbus_reply\x18" \x01(\x0b\x32&.perfetto.protos.SmbusReplyFtraceEventH\x00\x12\x43\n\x0elowmemory_kill\x18# \x01(\x0b\x32).perfetto.protos.LowmemoryKillFtraceEventH\x00\x12H\n\x11irq_handler_entry\x18$ \x01(\x0b\x32+.perfetto.protos.IrqHandlerEntryFtraceEventH\x00\x12\x46\n\x10irq_handler_exit\x18% \x01(\x0b\x32*.perfetto.protos.IrqHandlerExitFtraceEventH\x00\x12\x35\n\x07sync_pt\x18& \x01(\x0b\x32".perfetto.protos.SyncPtFtraceEventH\x00\x12\x41\n\rsync_timeline\x18\' \x01(\x0b\x32(.perfetto.protos.SyncTimelineFtraceEventH\x00\x12\x39\n\tsync_wait\x18( \x01(\x0b\x32$.perfetto.protos.SyncWaitFtraceEventH\x00\x12K\n\x13\x65xt4_da_write_begin\x18) \x01(\x0b\x32,.perfetto.protos.Ext4DaWriteBeginFtraceEventH\x00\x12G\n\x11\x65xt4_da_write_end\x18* \x01(\x0b\x32*.perfetto.protos.Ext4DaWriteEndFtraceEventH\x00\x12M\n\x14\x65xt4_sync_file_enter\x18+ \x01(\x0b\x32-.perfetto.protos.Ext4SyncFileEnterFtraceEventH\x00\x12K\n\x13\x65xt4_sync_file_exit\x18, \x01(\x0b\x32,.perfetto.protos.Ext4SyncFileExitFtraceEventH\x00\x12\x42\n\x0e\x62lock_rq_issue\x18- \x01(\x0b\x32(.perfetto.protos.BlockRqIssueFtraceEventH\x00\x12`\n\x1emm_vmscan_direct_reclaim_begin\x18. \x01(\x0b\x32\x36.perfetto.protos.MmVmscanDirectReclaimBeginFtraceEventH\x00\x12\\\n\x1cmm_vmscan_direct_reclaim_end\x18/ \x01(\x0b\x32\x34.perfetto.protos.MmVmscanDirectReclaimEndFtraceEventH\x00\x12O\n\x15mm_vmscan_kswapd_wake\x18\x30 \x01(\x0b\x32..perfetto.protos.MmVmscanKswapdWakeFtraceEventH\x00\x12Q\n\x16mm_vmscan_kswapd_sleep\x18\x31 \x01(\x0b\x32/.perfetto.protos.MmVmscanKswapdSleepFtraceEventH\x00\x12K\n\x12\x62inder_transaction\x18\x32 \x01(\x0b\x32-.perfetto.protos.BinderTransactionFtraceEventH\x00\x12\\\n\x1b\x62inder_transaction_received\x18\x33 \x01(\x0b\x32\x35.perfetto.protos.BinderTransactionReceivedFtraceEventH\x00\x12L\n\x13\x62inder_set_priority\x18\x34 \x01(\x0b\x32-.perfetto.protos.BinderSetPriorityFtraceEventH\x00\x12=\n\x0b\x62inder_lock\x18\x35 \x01(\x0b\x32&.perfetto.protos.BinderLockFtraceEventH\x00\x12\x41\n\rbinder_locked\x18\x36 \x01(\x0b\x32(.perfetto.protos.BinderLockedFtraceEventH\x00\x12\x41\n\rbinder_unlock\x18\x37 \x01(\x0b\x32(.perfetto.protos.BinderUnlockFtraceEventH\x00\x12T\n\x17workqueue_activate_work\x18\x38 \x01(\x0b\x32\x31.perfetto.protos.WorkqueueActivateWorkFtraceEventH\x00\x12P\n\x15workqueue_execute_end\x18\x39 \x01(\x0b\x32/.perfetto.protos.WorkqueueExecuteEndFtraceEventH\x00\x12T\n\x17workqueue_execute_start\x18: \x01(\x0b\x32\x31.perfetto.protos.WorkqueueExecuteStartFtraceEventH\x00\x12N\n\x14workqueue_queue_work\x18; \x01(\x0b\x32..perfetto.protos.WorkqueueQueueWorkFtraceEventH\x00\x12I\n\x11regulator_disable\x18< \x01(\x0b\x32,.perfetto.protos.RegulatorDisableFtraceEventH\x00\x12Z\n\x1aregulator_disable_complete\x18= \x01(\x0b\x32\x34.perfetto.protos.RegulatorDisableCompleteFtraceEventH\x00\x12G\n\x10regulator_enable\x18> \x01(\x0b\x32+.perfetto.protos.RegulatorEnableFtraceEventH\x00\x12X\n\x19regulator_enable_complete\x18? \x01(\x0b\x32\x33.perfetto.protos.RegulatorEnableCompleteFtraceEventH\x00\x12R\n\x16regulator_enable_delay\x18@ \x01(\x0b\x32\x30.perfetto.protos.RegulatorEnableDelayFtraceEventH\x00\x12P\n\x15regulator_set_voltage\x18\x41 \x01(\x0b\x32/.perfetto.protos.RegulatorSetVoltageFtraceEventH\x00\x12\x61\n\x1eregulator_set_voltage_complete\x18\x42 \x01(\x0b\x32\x37.perfetto.protos.RegulatorSetVoltageCompleteFtraceEventH\x00\x12J\n\x12\x63group_attach_task\x18\x43 \x01(\x0b\x32,.perfetto.protos.CgroupAttachTaskFtraceEventH\x00\x12?\n\x0c\x63group_mkdir\x18\x44 \x01(\x0b\x32\'.perfetto.protos.CgroupMkdirFtraceEventH\x00\x12\x43\n\x0e\x63group_remount\x18\x45 \x01(\x0b\x32).perfetto.protos.CgroupRemountFtraceEventH\x00\x12?\n\x0c\x63group_rmdir\x18\x46 \x01(\x0b\x32\'.perfetto.protos.CgroupRmdirFtraceEventH\x00\x12P\n\x15\x63group_transfer_tasks\x18G \x01(\x0b\x32/.perfetto.protos.CgroupTransferTasksFtraceEventH\x00\x12L\n\x13\x63group_destroy_root\x18H \x01(\x0b\x32-.perfetto.protos.CgroupDestroyRootFtraceEventH\x00\x12\x43\n\x0e\x63group_release\x18I \x01(\x0b\x32).perfetto.protos.CgroupReleaseFtraceEventH\x00\x12\x41\n\rcgroup_rename\x18J \x01(\x0b\x32(.perfetto.protos.CgroupRenameFtraceEventH\x00\x12H\n\x11\x63group_setup_root\x18K \x01(\x0b\x32+.perfetto.protos.CgroupSetupRootFtraceEventH\x00\x12\x44\n\x0fmdp_cmd_kickoff\x18L \x01(\x0b\x32).perfetto.protos.MdpCmdKickoffFtraceEventH\x00\x12;\n\nmdp_commit\x18M \x01(\x0b\x32%.perfetto.protos.MdpCommitFtraceEventH\x00\x12\x43\n\x0fmdp_perf_set_ot\x18N \x01(\x0b\x32(.perfetto.protos.MdpPerfSetOtFtraceEventH\x00\x12\x44\n\x0fmdp_sspp_change\x18O \x01(\x0b\x32).perfetto.protos.MdpSsppChangeFtraceEventH\x00\x12J\n\x12tracing_mark_write\x18P \x01(\x0b\x32,.perfetto.protos.TracingMarkWriteFtraceEventH\x00\x12O\n\x15mdp_cmd_pingpong_done\x18Q \x01(\x0b\x32..perfetto.protos.MdpCmdPingpongDoneFtraceEventH\x00\x12\x42\n\x0emdp_compare_bw\x18R \x01(\x0b\x32(.perfetto.protos.MdpCompareBwFtraceEventH\x00\x12R\n\x17mdp_perf_set_panic_luts\x18S \x01(\x0b\x32/.perfetto.protos.MdpPerfSetPanicLutsFtraceEventH\x00\x12>\n\x0cmdp_sspp_set\x18T \x01(\x0b\x32&.perfetto.protos.MdpSsppSetFtraceEventH\x00\x12M\n\x14mdp_cmd_readptr_done\x18U \x01(\x0b\x32-.perfetto.protos.MdpCmdReadptrDoneFtraceEventH\x00\x12>\n\x0cmdp_misr_crc\x18V \x01(\x0b\x32&.perfetto.protos.MdpMisrCrcFtraceEventH\x00\x12N\n\x15mdp_perf_set_qos_luts\x18W \x01(\x0b\x32-.perfetto.protos.MdpPerfSetQosLutsFtraceEventH\x00\x12H\n\x11mdp_trace_counter\x18X \x01(\x0b\x32+.perfetto.protos.MdpTraceCounterFtraceEventH\x00\x12I\n\x12mdp_cmd_release_bw\x18Y \x01(\x0b\x32+.perfetto.protos.MdpCmdReleaseBwFtraceEventH\x00\x12\x46\n\x10mdp_mixer_update\x18Z \x01(\x0b\x32*.perfetto.protos.MdpMixerUpdateFtraceEventH\x00\x12P\n\x16mdp_perf_set_wm_levels\x18[ \x01(\x0b\x32..perfetto.protos.MdpPerfSetWmLevelsFtraceEventH\x00\x12S\n\x17mdp_video_underrun_done\x18\\ \x01(\x0b\x32\x30.perfetto.protos.MdpVideoUnderrunDoneFtraceEventH\x00\x12O\n\x15mdp_cmd_wait_pingpong\x18] \x01(\x0b\x32..perfetto.protos.MdpCmdWaitPingpongFtraceEventH\x00\x12O\n\x15mdp_perf_prefill_calc\x18^ \x01(\x0b\x32..perfetto.protos.MdpPerfPrefillCalcFtraceEventH\x00\x12K\n\x13mdp_perf_update_bus\x18_ \x01(\x0b\x32,.perfetto.protos.MdpPerfUpdateBusFtraceEventH\x00\x12T\n\x18rotator_bw_ao_as_context\x18` \x01(\x0b\x32\x30.perfetto.protos.RotatorBwAoAsContextFtraceEventH\x00\x12[\n\x1cmm_filemap_add_to_page_cache\x18\x61 \x01(\x0b\x32\x33.perfetto.protos.MmFilemapAddToPageCacheFtraceEventH\x00\x12\x65\n!mm_filemap_delete_from_page_cache\x18\x62 \x01(\x0b\x32\x38.perfetto.protos.MmFilemapDeleteFromPageCacheFtraceEventH\x00\x12L\n\x13mm_compaction_begin\x18\x63 \x01(\x0b\x32-.perfetto.protos.MmCompactionBeginFtraceEventH\x00\x12\x61\n\x1emm_compaction_defer_compaction\x18\x64 \x01(\x0b\x32\x37.perfetto.protos.MmCompactionDeferCompactionFtraceEventH\x00\x12R\n\x16mm_compaction_deferred\x18\x65 \x01(\x0b\x32\x30.perfetto.protos.MmCompactionDeferredFtraceEventH\x00\x12W\n\x19mm_compaction_defer_reset\x18\x66 \x01(\x0b\x32\x32.perfetto.protos.MmCompactionDeferResetFtraceEventH\x00\x12H\n\x11mm_compaction_end\x18g \x01(\x0b\x32+.perfetto.protos.MmCompactionEndFtraceEventH\x00\x12R\n\x16mm_compaction_finished\x18h \x01(\x0b\x32\x30.perfetto.protos.MmCompactionFinishedFtraceEventH\x00\x12\x63\n\x1fmm_compaction_isolate_freepages\x18i \x01(\x0b\x32\x38.perfetto.protos.MmCompactionIsolateFreepagesFtraceEventH\x00\x12i\n"mm_compaction_isolate_migratepages\x18j \x01(\x0b\x32;.perfetto.protos.MmCompactionIsolateMigratepagesFtraceEventH\x00\x12_\n\x1dmm_compaction_kcompactd_sleep\x18k \x01(\x0b\x32\x36.perfetto.protos.MmCompactionKcompactdSleepFtraceEventH\x00\x12]\n\x1cmm_compaction_kcompactd_wake\x18l \x01(\x0b\x32\x35.perfetto.protos.MmCompactionKcompactdWakeFtraceEventH\x00\x12Z\n\x1amm_compaction_migratepages\x18m \x01(\x0b\x32\x34.perfetto.protos.MmCompactionMigratepagesFtraceEventH\x00\x12R\n\x16mm_compaction_suitable\x18n \x01(\x0b\x32\x30.perfetto.protos.MmCompactionSuitableFtraceEventH\x00\x12g\n"mm_compaction_try_to_compact_pages\x18o \x01(\x0b\x32\x39.perfetto.protos.MmCompactionTryToCompactPagesFtraceEventH\x00\x12\x61\n\x1emm_compaction_wakeup_kcompactd\x18p \x01(\x0b\x32\x37.perfetto.protos.MmCompactionWakeupKcompactdFtraceEventH\x00\x12\x43\n\x0esuspend_resume\x18q \x01(\x0b\x32).perfetto.protos.SuspendResumeFtraceEventH\x00\x12\x46\n\x10sched_wakeup_new\x18r \x01(\x0b\x32*.perfetto.protos.SchedWakeupNewFtraceEventH\x00\x12L\n\x13\x62lock_bio_backmerge\x18s \x01(\x0b\x32-.perfetto.protos.BlockBioBackmergeFtraceEventH\x00\x12\x46\n\x10\x62lock_bio_bounce\x18t \x01(\x0b\x32*.perfetto.protos.BlockBioBounceFtraceEventH\x00\x12J\n\x12\x62lock_bio_complete\x18u \x01(\x0b\x32,.perfetto.protos.BlockBioCompleteFtraceEventH\x00\x12N\n\x14\x62lock_bio_frontmerge\x18v \x01(\x0b\x32..perfetto.protos.BlockBioFrontmergeFtraceEventH\x00\x12\x44\n\x0f\x62lock_bio_queue\x18w \x01(\x0b\x32).perfetto.protos.BlockBioQueueFtraceEventH\x00\x12\x44\n\x0f\x62lock_bio_remap\x18x \x01(\x0b\x32).perfetto.protos.BlockBioRemapFtraceEventH\x00\x12J\n\x12\x62lock_dirty_buffer\x18y \x01(\x0b\x32,.perfetto.protos.BlockDirtyBufferFtraceEventH\x00\x12=\n\x0b\x62lock_getrq\x18z \x01(\x0b\x32&.perfetto.protos.BlockGetrqFtraceEventH\x00\x12;\n\nblock_plug\x18{ \x01(\x0b\x32%.perfetto.protos.BlockPlugFtraceEventH\x00\x12\x42\n\x0e\x62lock_rq_abort\x18| \x01(\x0b\x32(.perfetto.protos.BlockRqAbortFtraceEventH\x00\x12H\n\x11\x62lock_rq_complete\x18} \x01(\x0b\x32+.perfetto.protos.BlockRqCompleteFtraceEventH\x00\x12\x44\n\x0f\x62lock_rq_insert\x18~ \x01(\x0b\x32).perfetto.protos.BlockRqInsertFtraceEventH\x00\x12\x43\n\x0e\x62lock_rq_remap\x18\x80\x01 \x01(\x0b\x32(.perfetto.protos.BlockRqRemapFtraceEventH\x00\x12G\n\x10\x62lock_rq_requeue\x18\x81\x01 \x01(\x0b\x32*.perfetto.protos.BlockRqRequeueFtraceEventH\x00\x12\x42\n\rblock_sleeprq\x18\x82\x01 \x01(\x0b\x32(.perfetto.protos.BlockSleeprqFtraceEventH\x00\x12>\n\x0b\x62lock_split\x18\x83\x01 \x01(\x0b\x32&.perfetto.protos.BlockSplitFtraceEventH\x00\x12K\n\x12\x62lock_touch_buffer\x18\x84\x01 \x01(\x0b\x32,.perfetto.protos.BlockTouchBufferFtraceEventH\x00\x12@\n\x0c\x62lock_unplug\x18\x85\x01 \x01(\x0b\x32\'.perfetto.protos.BlockUnplugFtraceEventH\x00\x12N\n\x14\x65xt4_alloc_da_blocks\x18\x86\x01 \x01(\x0b\x32-.perfetto.protos.Ext4AllocDaBlocksFtraceEventH\x00\x12O\n\x14\x65xt4_allocate_blocks\x18\x87\x01 \x01(\x0b\x32..perfetto.protos.Ext4AllocateBlocksFtraceEventH\x00\x12M\n\x13\x65xt4_allocate_inode\x18\x88\x01 \x01(\x0b\x32-.perfetto.protos.Ext4AllocateInodeFtraceEventH\x00\x12\\\n\x1b\x65xt4_begin_ordered_truncate\x18\x89\x01 \x01(\x0b\x32\x34.perfetto.protos.Ext4BeginOrderedTruncateFtraceEventH\x00\x12M\n\x13\x65xt4_collapse_range\x18\x8a\x01 \x01(\x0b\x32-.perfetto.protos.Ext4CollapseRangeFtraceEventH\x00\x12P\n\x15\x65xt4_da_release_space\x18\x8b\x01 \x01(\x0b\x32..perfetto.protos.Ext4DaReleaseSpaceFtraceEventH\x00\x12P\n\x15\x65xt4_da_reserve_space\x18\x8c\x01 \x01(\x0b\x32..perfetto.protos.Ext4DaReserveSpaceFtraceEventH\x00\x12]\n\x1c\x65xt4_da_update_reserve_space\x18\x8d\x01 \x01(\x0b\x32\x34.perfetto.protos.Ext4DaUpdateReserveSpaceFtraceEventH\x00\x12L\n\x13\x65xt4_da_write_pages\x18\x8e\x01 \x01(\x0b\x32,.perfetto.protos.Ext4DaWritePagesFtraceEventH\x00\x12Y\n\x1a\x65xt4_da_write_pages_extent\x18\x8f\x01 \x01(\x0b\x32\x32.perfetto.protos.Ext4DaWritePagesExtentFtraceEventH\x00\x12N\n\x14\x65xt4_direct_IO_enter\x18\x90\x01 \x01(\x0b\x32-.perfetto.protos.Ext4DirectIOEnterFtraceEventH\x00\x12L\n\x13\x65xt4_direct_IO_exit\x18\x91\x01 \x01(\x0b\x32,.perfetto.protos.Ext4DirectIOExitFtraceEventH\x00\x12M\n\x13\x65xt4_discard_blocks\x18\x92\x01 \x01(\x0b\x32-.perfetto.protos.Ext4DiscardBlocksFtraceEventH\x00\x12]\n\x1b\x65xt4_discard_preallocations\x18\x93\x01 \x01(\x0b\x32\x35.perfetto.protos.Ext4DiscardPreallocationsFtraceEventH\x00\x12\x45\n\x0f\x65xt4_drop_inode\x18\x94\x01 \x01(\x0b\x32).perfetto.protos.Ext4DropInodeFtraceEventH\x00\x12N\n\x14\x65xt4_es_cache_extent\x18\x95\x01 \x01(\x0b\x32-.perfetto.protos.Ext4EsCacheExtentFtraceEventH\x00\x12q\n\'ext4_es_find_delayed_extent_range_enter\x18\x96\x01 \x01(\x0b\x32=.perfetto.protos.Ext4EsFindDelayedExtentRangeEnterFtraceEventH\x00\x12o\n&ext4_es_find_delayed_extent_range_exit\x18\x97\x01 \x01(\x0b\x32<.perfetto.protos.Ext4EsFindDelayedExtentRangeExitFtraceEventH\x00\x12P\n\x15\x65xt4_es_insert_extent\x18\x98\x01 \x01(\x0b\x32..perfetto.protos.Ext4EsInsertExtentFtraceEventH\x00\x12[\n\x1b\x65xt4_es_lookup_extent_enter\x18\x99\x01 \x01(\x0b\x32\x33.perfetto.protos.Ext4EsLookupExtentEnterFtraceEventH\x00\x12Y\n\x1a\x65xt4_es_lookup_extent_exit\x18\x9a\x01 \x01(\x0b\x32\x32.perfetto.protos.Ext4EsLookupExtentExitFtraceEventH\x00\x12P\n\x15\x65xt4_es_remove_extent\x18\x9b\x01 \x01(\x0b\x32..perfetto.protos.Ext4EsRemoveExtentFtraceEventH\x00\x12\x43\n\x0e\x65xt4_es_shrink\x18\x9c\x01 \x01(\x0b\x32(.perfetto.protos.Ext4EsShrinkFtraceEventH\x00\x12N\n\x14\x65xt4_es_shrink_count\x18\x9d\x01 \x01(\x0b\x32-.perfetto.protos.Ext4EsShrinkCountFtraceEventH\x00\x12W\n\x19\x65xt4_es_shrink_scan_enter\x18\x9e\x01 \x01(\x0b\x32\x31.perfetto.protos.Ext4EsShrinkScanEnterFtraceEventH\x00\x12U\n\x18\x65xt4_es_shrink_scan_exit\x18\x9f\x01 \x01(\x0b\x32\x30.perfetto.protos.Ext4EsShrinkScanExitFtraceEventH\x00\x12G\n\x10\x65xt4_evict_inode\x18\xa0\x01 \x01(\x0b\x32*.perfetto.protos.Ext4EvictInodeFtraceEventH\x00\x12n\n%ext4_ext_convert_to_initialized_enter\x18\xa1\x01 \x01(\x0b\x32<.perfetto.protos.Ext4ExtConvertToInitializedEnterFtraceEventH\x00\x12t\n(ext4_ext_convert_to_initialized_fastpath\x18\xa2\x01 \x01(\x0b\x32?.perfetto.protos.Ext4ExtConvertToInitializedFastpathFtraceEventH\x00\x12g\n!ext4_ext_handle_unwritten_extents\x18\xa3\x01 \x01(\x0b\x32\x39.perfetto.protos.Ext4ExtHandleUnwrittenExtentsFtraceEventH\x00\x12H\n\x11\x65xt4_ext_in_cache\x18\xa4\x01 \x01(\x0b\x32*.perfetto.protos.Ext4ExtInCacheFtraceEventH\x00\x12N\n\x14\x65xt4_ext_load_extent\x18\xa5\x01 \x01(\x0b\x32-.perfetto.protos.Ext4ExtLoadExtentFtraceEventH\x00\x12W\n\x19\x65xt4_ext_map_blocks_enter\x18\xa6\x01 \x01(\x0b\x32\x31.perfetto.protos.Ext4ExtMapBlocksEnterFtraceEventH\x00\x12U\n\x18\x65xt4_ext_map_blocks_exit\x18\xa7\x01 \x01(\x0b\x32\x30.perfetto.protos.Ext4ExtMapBlocksExitFtraceEventH\x00\x12O\n\x15\x65xt4_ext_put_in_cache\x18\xa8\x01 \x01(\x0b\x32-.perfetto.protos.Ext4ExtPutInCacheFtraceEventH\x00\x12P\n\x15\x65xt4_ext_remove_space\x18\xa9\x01 \x01(\x0b\x32..perfetto.protos.Ext4ExtRemoveSpaceFtraceEventH\x00\x12Y\n\x1a\x65xt4_ext_remove_space_done\x18\xaa\x01 \x01(\x0b\x32\x32.perfetto.protos.Ext4ExtRemoveSpaceDoneFtraceEventH\x00\x12\x44\n\x0f\x65xt4_ext_rm_idx\x18\xab\x01 \x01(\x0b\x32(.perfetto.protos.Ext4ExtRmIdxFtraceEventH\x00\x12\x46\n\x10\x65xt4_ext_rm_leaf\x18\xac\x01 \x01(\x0b\x32).perfetto.protos.Ext4ExtRmLeafFtraceEventH\x00\x12N\n\x14\x65xt4_ext_show_extent\x18\xad\x01 \x01(\x0b\x32-.perfetto.protos.Ext4ExtShowExtentFtraceEventH\x00\x12O\n\x14\x65xt4_fallocate_enter\x18\xae\x01 \x01(\x0b\x32..perfetto.protos.Ext4FallocateEnterFtraceEventH\x00\x12M\n\x13\x65xt4_fallocate_exit\x18\xaf\x01 \x01(\x0b\x32-.perfetto.protos.Ext4FallocateExitFtraceEventH\x00\x12V\n\x18\x65xt4_find_delalloc_range\x18\xb0\x01 \x01(\x0b\x32\x31.perfetto.protos.Ext4FindDelallocRangeFtraceEventH\x00\x12>\n\x0b\x65xt4_forget\x18\xb1\x01 \x01(\x0b\x32&.perfetto.protos.Ext4ForgetFtraceEventH\x00\x12G\n\x10\x65xt4_free_blocks\x18\xb2\x01 \x01(\x0b\x32*.perfetto.protos.Ext4FreeBlocksFtraceEventH\x00\x12\x45\n\x0f\x65xt4_free_inode\x18\xb3\x01 \x01(\x0b\x32).perfetto.protos.Ext4FreeInodeFtraceEventH\x00\x12j\n#ext4_get_implied_cluster_alloc_exit\x18\xb4\x01 \x01(\x0b\x32:.perfetto.protos.Ext4GetImpliedClusterAllocExitFtraceEventH\x00\x12\x63\n\x1f\x65xt4_get_reserved_cluster_alloc\x18\xb5\x01 \x01(\x0b\x32\x37.perfetto.protos.Ext4GetReservedClusterAllocFtraceEventH\x00\x12W\n\x19\x65xt4_ind_map_blocks_enter\x18\xb6\x01 \x01(\x0b\x32\x31.perfetto.protos.Ext4IndMapBlocksEnterFtraceEventH\x00\x12U\n\x18\x65xt4_ind_map_blocks_exit\x18\xb7\x01 \x01(\x0b\x32\x30.perfetto.protos.Ext4IndMapBlocksExitFtraceEventH\x00\x12I\n\x11\x65xt4_insert_range\x18\xb8\x01 \x01(\x0b\x32+.perfetto.protos.Ext4InsertRangeFtraceEventH\x00\x12N\n\x13\x65xt4_invalidatepage\x18\xb9\x01 \x01(\x0b\x32..perfetto.protos.Ext4InvalidatepageFtraceEventH\x00\x12K\n\x12\x65xt4_journal_start\x18\xba\x01 \x01(\x0b\x32,.perfetto.protos.Ext4JournalStartFtraceEventH\x00\x12\\\n\x1b\x65xt4_journal_start_reserved\x18\xbb\x01 \x01(\x0b\x32\x34.perfetto.protos.Ext4JournalStartReservedFtraceEventH\x00\x12\x63\n\x1e\x65xt4_journalled_invalidatepage\x18\xbc\x01 \x01(\x0b\x32\x38.perfetto.protos.Ext4JournalledInvalidatepageFtraceEventH\x00\x12X\n\x19\x65xt4_journalled_write_end\x18\xbd\x01 \x01(\x0b\x32\x32.perfetto.protos.Ext4JournalledWriteEndFtraceEventH\x00\x12\x45\n\x0f\x65xt4_load_inode\x18\xbe\x01 \x01(\x0b\x32).perfetto.protos.Ext4LoadInodeFtraceEventH\x00\x12R\n\x16\x65xt4_load_inode_bitmap\x18\xbf\x01 \x01(\x0b\x32/.perfetto.protos.Ext4LoadInodeBitmapFtraceEventH\x00\x12P\n\x15\x65xt4_mark_inode_dirty\x18\xc0\x01 \x01(\x0b\x32..perfetto.protos.Ext4MarkInodeDirtyFtraceEventH\x00\x12L\n\x13\x65xt4_mb_bitmap_load\x18\xc1\x01 \x01(\x0b\x32,.perfetto.protos.Ext4MbBitmapLoadFtraceEventH\x00\x12W\n\x19\x65xt4_mb_buddy_bitmap_load\x18\xc2\x01 \x01(\x0b\x32\x31.perfetto.protos.Ext4MbBuddyBitmapLoadFtraceEventH\x00\x12\x62\n\x1e\x65xt4_mb_discard_preallocations\x18\xc3\x01 \x01(\x0b\x32\x37.perfetto.protos.Ext4MbDiscardPreallocationsFtraceEventH\x00\x12M\n\x14\x65xt4_mb_new_group_pa\x18\xc4\x01 \x01(\x0b\x32,.perfetto.protos.Ext4MbNewGroupPaFtraceEventH\x00\x12M\n\x14\x65xt4_mb_new_inode_pa\x18\xc5\x01 \x01(\x0b\x32,.perfetto.protos.Ext4MbNewInodePaFtraceEventH\x00\x12U\n\x18\x65xt4_mb_release_group_pa\x18\xc6\x01 \x01(\x0b\x32\x30.perfetto.protos.Ext4MbReleaseGroupPaFtraceEventH\x00\x12U\n\x18\x65xt4_mb_release_inode_pa\x18\xc7\x01 \x01(\x0b\x32\x30.perfetto.protos.Ext4MbReleaseInodePaFtraceEventH\x00\x12K\n\x12\x65xt4_mballoc_alloc\x18\xc8\x01 \x01(\x0b\x32,.perfetto.protos.Ext4MballocAllocFtraceEventH\x00\x12O\n\x14\x65xt4_mballoc_discard\x18\xc9\x01 \x01(\x0b\x32..perfetto.protos.Ext4MballocDiscardFtraceEventH\x00\x12I\n\x11\x65xt4_mballoc_free\x18\xca\x01 \x01(\x0b\x32+.perfetto.protos.Ext4MballocFreeFtraceEventH\x00\x12Q\n\x15\x65xt4_mballoc_prealloc\x18\xcb\x01 \x01(\x0b\x32/.perfetto.protos.Ext4MballocPreallocFtraceEventH\x00\x12]\n\x1c\x65xt4_other_inode_update_time\x18\xcc\x01 \x01(\x0b\x32\x34.perfetto.protos.Ext4OtherInodeUpdateTimeFtraceEventH\x00\x12\x45\n\x0f\x65xt4_punch_hole\x18\xcd\x01 \x01(\x0b\x32).perfetto.protos.Ext4PunchHoleFtraceEventH\x00\x12[\n\x1b\x65xt4_read_block_bitmap_load\x18\xce\x01 \x01(\x0b\x32\x33.perfetto.protos.Ext4ReadBlockBitmapLoadFtraceEventH\x00\x12\x42\n\rext4_readpage\x18\xcf\x01 \x01(\x0b\x32(.perfetto.protos.Ext4ReadpageFtraceEventH\x00\x12H\n\x10\x65xt4_releasepage\x18\xd0\x01 \x01(\x0b\x32+.perfetto.protos.Ext4ReleasepageFtraceEventH\x00\x12K\n\x12\x65xt4_remove_blocks\x18\xd1\x01 \x01(\x0b\x32,.perfetto.protos.Ext4RemoveBlocksFtraceEventH\x00\x12M\n\x13\x65xt4_request_blocks\x18\xd2\x01 \x01(\x0b\x32-.perfetto.protos.Ext4RequestBlocksFtraceEventH\x00\x12K\n\x12\x65xt4_request_inode\x18\xd3\x01 \x01(\x0b\x32,.perfetto.protos.Ext4RequestInodeFtraceEventH\x00\x12?\n\x0c\x65xt4_sync_fs\x18\xd4\x01 \x01(\x0b\x32&.perfetto.protos.Ext4SyncFsFtraceEventH\x00\x12J\n\x12\x65xt4_trim_all_free\x18\xd5\x01 \x01(\x0b\x32+.perfetto.protos.Ext4TrimAllFreeFtraceEventH\x00\x12G\n\x10\x65xt4_trim_extent\x18\xd6\x01 \x01(\x0b\x32*.perfetto.protos.Ext4TrimExtentFtraceEventH\x00\x12M\n\x13\x65xt4_truncate_enter\x18\xd7\x01 \x01(\x0b\x32-.perfetto.protos.Ext4TruncateEnterFtraceEventH\x00\x12K\n\x12\x65xt4_truncate_exit\x18\xd8\x01 \x01(\x0b\x32,.perfetto.protos.Ext4TruncateExitFtraceEventH\x00\x12I\n\x11\x65xt4_unlink_enter\x18\xd9\x01 \x01(\x0b\x32+.perfetto.protos.Ext4UnlinkEnterFtraceEventH\x00\x12G\n\x10\x65xt4_unlink_exit\x18\xda\x01 \x01(\x0b\x32*.perfetto.protos.Ext4UnlinkExitFtraceEventH\x00\x12G\n\x10\x65xt4_write_begin\x18\xdb\x01 \x01(\x0b\x32*.perfetto.protos.Ext4WriteBeginFtraceEventH\x00\x12\x43\n\x0e\x65xt4_write_end\x18\xe6\x01 \x01(\x0b\x32(.perfetto.protos.Ext4WriteEndFtraceEventH\x00\x12\x44\n\x0e\x65xt4_writepage\x18\xe7\x01 \x01(\x0b\x32).perfetto.protos.Ext4WritepageFtraceEventH\x00\x12\x46\n\x0f\x65xt4_writepages\x18\xe8\x01 \x01(\x0b\x32*.perfetto.protos.Ext4WritepagesFtraceEventH\x00\x12S\n\x16\x65xt4_writepages_result\x18\xe9\x01 \x01(\x0b\x32\x30.perfetto.protos.Ext4WritepagesResultFtraceEventH\x00\x12\x45\n\x0f\x65xt4_zero_range\x18\xea\x01 \x01(\x0b\x32).perfetto.protos.Ext4ZeroRangeFtraceEventH\x00\x12@\n\x0ctask_newtask\x18\xeb\x01 \x01(\x0b\x32\'.perfetto.protos.TaskNewtaskFtraceEventH\x00\x12>\n\x0btask_rename\x18\xec\x01 \x01(\x0b\x32&.perfetto.protos.TaskRenameFtraceEventH\x00\x12K\n\x12sched_process_exec\x18\xed\x01 \x01(\x0b\x32,.perfetto.protos.SchedProcessExecFtraceEventH\x00\x12K\n\x12sched_process_exit\x18\xee\x01 \x01(\x0b\x32,.perfetto.protos.SchedProcessExitFtraceEventH\x00\x12K\n\x12sched_process_fork\x18\xef\x01 \x01(\x0b\x32,.perfetto.protos.SchedProcessForkFtraceEventH\x00\x12K\n\x12sched_process_free\x18\xf0\x01 \x01(\x0b\x32,.perfetto.protos.SchedProcessFreeFtraceEventH\x00\x12K\n\x12sched_process_hang\x18\xf1\x01 \x01(\x0b\x32,.perfetto.protos.SchedProcessHangFtraceEventH\x00\x12K\n\x12sched_process_wait\x18\xf2\x01 \x01(\x0b\x32,.perfetto.protos.SchedProcessWaitFtraceEventH\x00\x12J\n\x12\x66\x32\x66s_do_submit_bio\x18\xf3\x01 \x01(\x0b\x32+.perfetto.protos.F2fsDoSubmitBioFtraceEventH\x00\x12G\n\x10\x66\x32\x66s_evict_inode\x18\xf4\x01 \x01(\x0b\x32*.perfetto.protos.F2fsEvictInodeFtraceEventH\x00\x12\x44\n\x0e\x66\x32\x66s_fallocate\x18\xf5\x01 \x01(\x0b\x32).perfetto.protos.F2fsFallocateFtraceEventH\x00\x12L\n\x13\x66\x32\x66s_get_data_block\x18\xf6\x01 \x01(\x0b\x32,.perfetto.protos.F2fsGetDataBlockFtraceEventH\x00\x12\x45\n\x0f\x66\x32\x66s_get_victim\x18\xf7\x01 \x01(\x0b\x32).perfetto.protos.F2fsGetVictimFtraceEventH\x00\x12:\n\tf2fs_iget\x18\xf8\x01 \x01(\x0b\x32$.perfetto.protos.F2fsIgetFtraceEventH\x00\x12\x43\n\x0e\x66\x32\x66s_iget_exit\x18\xf9\x01 \x01(\x0b\x32(.perfetto.protos.F2fsIgetExitFtraceEventH\x00\x12\x43\n\x0e\x66\x32\x66s_new_inode\x18\xfa\x01 \x01(\x0b\x32(.perfetto.protos.F2fsNewInodeFtraceEventH\x00\x12\x42\n\rf2fs_readpage\x18\xfb\x01 \x01(\x0b\x32(.perfetto.protos.F2fsReadpageFtraceEventH\x00\x12R\n\x16\x66\x32\x66s_reserve_new_block\x18\xfc\x01 \x01(\x0b\x32/.perfetto.protos.F2fsReserveNewBlockFtraceEventH\x00\x12L\n\x13\x66\x32\x66s_set_page_dirty\x18\xfd\x01 \x01(\x0b\x32,.perfetto.protos.F2fsSetPageDirtyFtraceEventH\x00\x12R\n\x16\x66\x32\x66s_submit_write_page\x18\xfe\x01 \x01(\x0b\x32/.perfetto.protos.F2fsSubmitWritePageFtraceEventH\x00\x12N\n\x14\x66\x32\x66s_sync_file_enter\x18\xff\x01 \x01(\x0b\x32-.perfetto.protos.F2fsSyncFileEnterFtraceEventH\x00\x12L\n\x13\x66\x32\x66s_sync_file_exit\x18\x80\x02 \x01(\x0b\x32,.perfetto.protos.F2fsSyncFileExitFtraceEventH\x00\x12?\n\x0c\x66\x32\x66s_sync_fs\x18\x81\x02 \x01(\x0b\x32&.perfetto.protos.F2fsSyncFsFtraceEventH\x00\x12\x42\n\rf2fs_truncate\x18\x82\x02 \x01(\x0b\x32(.perfetto.protos.F2fsTruncateFtraceEventH\x00\x12Z\n\x1a\x66\x32\x66s_truncate_blocks_enter\x18\x83\x02 \x01(\x0b\x32\x33.perfetto.protos.F2fsTruncateBlocksEnterFtraceEventH\x00\x12X\n\x19\x66\x32\x66s_truncate_blocks_exit\x18\x84\x02 \x01(\x0b\x32\x32.perfetto.protos.F2fsTruncateBlocksExitFtraceEventH\x00\x12\x63\n\x1f\x66\x32\x66s_truncate_data_blocks_range\x18\x85\x02 \x01(\x0b\x32\x37.perfetto.protos.F2fsTruncateDataBlocksRangeFtraceEventH\x00\x12\x65\n f2fs_truncate_inode_blocks_enter\x18\x86\x02 \x01(\x0b\x32\x38.perfetto.protos.F2fsTruncateInodeBlocksEnterFtraceEventH\x00\x12\x63\n\x1f\x66\x32\x66s_truncate_inode_blocks_exit\x18\x87\x02 \x01(\x0b\x32\x37.perfetto.protos.F2fsTruncateInodeBlocksExitFtraceEventH\x00\x12K\n\x12\x66\x32\x66s_truncate_node\x18\x88\x02 \x01(\x0b\x32,.perfetto.protos.F2fsTruncateNodeFtraceEventH\x00\x12X\n\x19\x66\x32\x66s_truncate_nodes_enter\x18\x89\x02 \x01(\x0b\x32\x32.perfetto.protos.F2fsTruncateNodesEnterFtraceEventH\x00\x12V\n\x18\x66\x32\x66s_truncate_nodes_exit\x18\x8a\x02 \x01(\x0b\x32\x31.perfetto.protos.F2fsTruncateNodesExitFtraceEventH\x00\x12\\\n\x1b\x66\x32\x66s_truncate_partial_nodes\x18\x8b\x02 \x01(\x0b\x32\x34.perfetto.protos.F2fsTruncatePartialNodesFtraceEventH\x00\x12I\n\x11\x66\x32\x66s_unlink_enter\x18\x8c\x02 \x01(\x0b\x32+.perfetto.protos.F2fsUnlinkEnterFtraceEventH\x00\x12G\n\x10\x66\x32\x66s_unlink_exit\x18\x8d\x02 \x01(\x0b\x32*.perfetto.protos.F2fsUnlinkExitFtraceEventH\x00\x12N\n\x14\x66\x32\x66s_vm_page_mkwrite\x18\x8e\x02 \x01(\x0b\x32-.perfetto.protos.F2fsVmPageMkwriteFtraceEventH\x00\x12G\n\x10\x66\x32\x66s_write_begin\x18\x8f\x02 \x01(\x0b\x32*.perfetto.protos.F2fsWriteBeginFtraceEventH\x00\x12Q\n\x15\x66\x32\x66s_write_checkpoint\x18\x90\x02 \x01(\x0b\x32/.perfetto.protos.F2fsWriteCheckpointFtraceEventH\x00\x12\x43\n\x0e\x66\x32\x66s_write_end\x18\x91\x02 \x01(\x0b\x32(.perfetto.protos.F2fsWriteEndFtraceEventH\x00\x12P\n\x15\x61lloc_pages_iommu_end\x18\x92\x02 \x01(\x0b\x32..perfetto.protos.AllocPagesIommuEndFtraceEventH\x00\x12R\n\x16\x61lloc_pages_iommu_fail\x18\x93\x02 \x01(\x0b\x32/.perfetto.protos.AllocPagesIommuFailFtraceEventH\x00\x12T\n\x17\x61lloc_pages_iommu_start\x18\x94\x02 \x01(\x0b\x32\x30.perfetto.protos.AllocPagesIommuStartFtraceEventH\x00\x12L\n\x13\x61lloc_pages_sys_end\x18\x95\x02 \x01(\x0b\x32,.perfetto.protos.AllocPagesSysEndFtraceEventH\x00\x12N\n\x14\x61lloc_pages_sys_fail\x18\x96\x02 \x01(\x0b\x32-.perfetto.protos.AllocPagesSysFailFtraceEventH\x00\x12P\n\x15\x61lloc_pages_sys_start\x18\x97\x02 \x01(\x0b\x32..perfetto.protos.AllocPagesSysStartFtraceEventH\x00\x12Z\n\x1a\x64ma_alloc_contiguous_retry\x18\x98\x02 \x01(\x0b\x32\x33.perfetto.protos.DmaAllocContiguousRetryFtraceEventH\x00\x12\x45\n\x0fiommu_map_range\x18\x99\x02 \x01(\x0b\x32).perfetto.protos.IommuMapRangeFtraceEventH\x00\x12\\\n\x1ciommu_sec_ptbl_map_range_end\x18\x9a\x02 \x01(\x0b\x32\x33.perfetto.protos.IommuSecPtblMapRangeEndFtraceEventH\x00\x12`\n\x1eiommu_sec_ptbl_map_range_start\x18\x9b\x02 \x01(\x0b\x32\x35.perfetto.protos.IommuSecPtblMapRangeStartFtraceEventH\x00\x12N\n\x14ion_alloc_buffer_end\x18\x9c\x02 \x01(\x0b\x32-.perfetto.protos.IonAllocBufferEndFtraceEventH\x00\x12P\n\x15ion_alloc_buffer_fail\x18\x9d\x02 \x01(\x0b\x32..perfetto.protos.IonAllocBufferFailFtraceEventH\x00\x12X\n\x19ion_alloc_buffer_fallback\x18\x9e\x02 \x01(\x0b\x32\x32.perfetto.protos.IonAllocBufferFallbackFtraceEventH\x00\x12R\n\x16ion_alloc_buffer_start\x18\x9f\x02 \x01(\x0b\x32/.perfetto.protos.IonAllocBufferStartFtraceEventH\x00\x12J\n\x12ion_cp_alloc_retry\x18\xa0\x02 \x01(\x0b\x32+.perfetto.protos.IonCpAllocRetryFtraceEventH\x00\x12U\n\x18ion_cp_secure_buffer_end\x18\xa1\x02 \x01(\x0b\x32\x30.perfetto.protos.IonCpSecureBufferEndFtraceEventH\x00\x12Y\n\x1aion_cp_secure_buffer_start\x18\xa2\x02 \x01(\x0b\x32\x32.perfetto.protos.IonCpSecureBufferStartFtraceEventH\x00\x12\x46\n\x0fion_prefetching\x18\xa3\x02 \x01(\x0b\x32*.perfetto.protos.IonPrefetchingFtraceEventH\x00\x12_\n\x1eion_secure_cma_add_to_pool_end\x18\xa4\x02 \x01(\x0b\x32\x34.perfetto.protos.IonSecureCmaAddToPoolEndFtraceEventH\x00\x12\x63\n ion_secure_cma_add_to_pool_start\x18\xa5\x02 \x01(\x0b\x32\x36.perfetto.protos.IonSecureCmaAddToPoolStartFtraceEventH\x00\x12[\n\x1bion_secure_cma_allocate_end\x18\xa6\x02 \x01(\x0b\x32\x33.perfetto.protos.IonSecureCmaAllocateEndFtraceEventH\x00\x12_\n\x1dion_secure_cma_allocate_start\x18\xa7\x02 \x01(\x0b\x32\x35.perfetto.protos.IonSecureCmaAllocateStartFtraceEventH\x00\x12`\n\x1eion_secure_cma_shrink_pool_end\x18\xa8\x02 \x01(\x0b\x32\x35.perfetto.protos.IonSecureCmaShrinkPoolEndFtraceEventH\x00\x12\x64\n ion_secure_cma_shrink_pool_start\x18\xa9\x02 \x01(\x0b\x32\x37.perfetto.protos.IonSecureCmaShrinkPoolStartFtraceEventH\x00\x12\x33\n\x05kfree\x18\xaa\x02 \x01(\x0b\x32!.perfetto.protos.KfreeFtraceEventH\x00\x12\x37\n\x07kmalloc\x18\xab\x02 \x01(\x0b\x32#.perfetto.protos.KmallocFtraceEventH\x00\x12@\n\x0ckmalloc_node\x18\xac\x02 \x01(\x0b\x32\'.perfetto.protos.KmallocNodeFtraceEventH\x00\x12G\n\x10kmem_cache_alloc\x18\xad\x02 \x01(\x0b\x32*.perfetto.protos.KmemCacheAllocFtraceEventH\x00\x12P\n\x15kmem_cache_alloc_node\x18\xae\x02 \x01(\x0b\x32..perfetto.protos.KmemCacheAllocNodeFtraceEventH\x00\x12\x45\n\x0fkmem_cache_free\x18\xaf\x02 \x01(\x0b\x32).perfetto.protos.KmemCacheFreeFtraceEventH\x00\x12I\n\x11migrate_pages_end\x18\xb0\x02 \x01(\x0b\x32+.perfetto.protos.MigratePagesEndFtraceEventH\x00\x12M\n\x13migrate_pages_start\x18\xb1\x02 \x01(\x0b\x32-.perfetto.protos.MigratePagesStartFtraceEventH\x00\x12\x42\n\rmigrate_retry\x18\xb2\x02 \x01(\x0b\x32(.perfetto.protos.MigrateRetryFtraceEventH\x00\x12\x41\n\rmm_page_alloc\x18\xb3\x02 \x01(\x0b\x32\'.perfetto.protos.MmPageAllocFtraceEventH\x00\x12P\n\x15mm_page_alloc_extfrag\x18\xb4\x02 \x01(\x0b\x32..perfetto.protos.MmPageAllocExtfragFtraceEventH\x00\x12W\n\x19mm_page_alloc_zone_locked\x18\xb5\x02 \x01(\x0b\x32\x31.perfetto.protos.MmPageAllocZoneLockedFtraceEventH\x00\x12?\n\x0cmm_page_free\x18\xb6\x02 \x01(\x0b\x32&.perfetto.protos.MmPageFreeFtraceEventH\x00\x12N\n\x14mm_page_free_batched\x18\xb7\x02 \x01(\x0b\x32-.perfetto.protos.MmPageFreeBatchedFtraceEventH\x00\x12J\n\x12mm_page_pcpu_drain\x18\xb8\x02 \x01(\x0b\x32+.perfetto.protos.MmPagePcpuDrainFtraceEventH\x00\x12\x38\n\x08rss_stat\x18\xb9\x02 \x01(\x0b\x32#.perfetto.protos.RssStatFtraceEventH\x00\x12\x45\n\x0fion_heap_shrink\x18\xba\x02 \x01(\x0b\x32).perfetto.protos.IonHeapShrinkFtraceEventH\x00\x12\x41\n\rion_heap_grow\x18\xbb\x02 \x01(\x0b\x32\'.perfetto.protos.IonHeapGrowFtraceEventH\x00\x12<\n\nfence_init\x18\xbc\x02 \x01(\x0b\x32%.perfetto.protos.FenceInitFtraceEventH\x00\x12\x42\n\rfence_destroy\x18\xbd\x02 \x01(\x0b\x32(.perfetto.protos.FenceDestroyFtraceEventH\x00\x12M\n\x13\x66\x65nce_enable_signal\x18\xbe\x02 \x01(\x0b\x32-.perfetto.protos.FenceEnableSignalFtraceEventH\x00\x12\x44\n\x0e\x66\x65nce_signaled\x18\xbf\x02 \x01(\x0b\x32).perfetto.protos.FenceSignaledFtraceEventH\x00\x12<\n\nclk_enable\x18\xc0\x02 \x01(\x0b\x32%.perfetto.protos.ClkEnableFtraceEventH\x00\x12>\n\x0b\x63lk_disable\x18\xc1\x02 \x01(\x0b\x32&.perfetto.protos.ClkDisableFtraceEventH\x00\x12?\n\x0c\x63lk_set_rate\x18\xc2\x02 \x01(\x0b\x32&.perfetto.protos.ClkSetRateFtraceEventH\x00\x12^\n\x1c\x62inder_transaction_alloc_buf\x18\xc3\x02 \x01(\x0b\x32\x35.perfetto.protos.BinderTransactionAllocBufFtraceEventH\x00\x12\x44\n\x0esignal_deliver\x18\xc4\x02 \x01(\x0b\x32).perfetto.protos.SignalDeliverFtraceEventH\x00\x12\x46\n\x0fsignal_generate\x18\xc5\x02 \x01(\x0b\x32*.perfetto.protos.SignalGenerateFtraceEventH\x00\x12N\n\x14oom_score_adj_update\x18\xc6\x02 \x01(\x0b\x32-.perfetto.protos.OomScoreAdjUpdateFtraceEventH\x00\x12\x37\n\x07generic\x18\xc7\x02 \x01(\x0b\x32#.perfetto.protos.GenericFtraceEventH\x00\x12\x45\n\x0fmm_event_record\x18\xc8\x02 \x01(\x0b\x32).perfetto.protos.MmEventRecordFtraceEventH\x00\x12:\n\tsys_enter\x18\xc9\x02 \x01(\x0b\x32$.perfetto.protos.SysEnterFtraceEventH\x00\x12\x38\n\x08sys_exit\x18\xca\x02 \x01(\x0b\x32#.perfetto.protos.SysExitFtraceEventH\x00\x12\x31\n\x04zero\x18\xcb\x02 \x01(\x0b\x32 .perfetto.protos.ZeroFtraceEventH\x00\x12\x42\n\rgpu_frequency\x18\xcc\x02 \x01(\x0b\x32(.perfetto.protos.GpuFrequencyFtraceEventH\x00\x12R\n\x16sde_tracing_mark_write\x18\xcd\x02 \x01(\x0b\x32/.perfetto.protos.SdeTracingMarkWriteFtraceEventH\x00\x12>\n\x0bmark_victim\x18\xce\x02 \x01(\x0b\x32&.perfetto.protos.MarkVictimFtraceEventH\x00\x12\x38\n\x08ion_stat\x18\xcf\x02 \x01(\x0b\x32#.perfetto.protos.IonStatFtraceEventH\x00\x12I\n\x11ion_buffer_create\x18\xd0\x02 \x01(\x0b\x32+.perfetto.protos.IonBufferCreateFtraceEventH\x00\x12K\n\x12ion_buffer_destroy\x18\xd1\x02 \x01(\x0b\x32,.perfetto.protos.IonBufferDestroyFtraceEventH\x00\x12\x43\n\x0escm_call_start\x18\xd2\x02 \x01(\x0b\x32(.perfetto.protos.ScmCallStartFtraceEventH\x00\x12?\n\x0cscm_call_end\x18\xd3\x02 \x01(\x0b\x32&.perfetto.protos.ScmCallEndFtraceEventH\x00\x12\x41\n\rgpu_mem_total\x18\xd4\x02 \x01(\x0b\x32\'.perfetto.protos.GpuMemTotalFtraceEventH\x00\x12N\n\x13thermal_temperature\x18\xd5\x02 \x01(\x0b\x32..perfetto.protos.ThermalTemperatureFtraceEventH\x00\x12>\n\x0b\x63\x64\x65v_update\x18\xd6\x02 \x01(\x0b\x32&.perfetto.protos.CdevUpdateFtraceEventH\x00\x12<\n\ncpuhp_exit\x18\xd7\x02 \x01(\x0b\x32%.perfetto.protos.CpuhpExitFtraceEventH\x00\x12I\n\x11\x63puhp_multi_enter\x18\xd8\x02 \x01(\x0b\x32+.perfetto.protos.CpuhpMultiEnterFtraceEventH\x00\x12>\n\x0b\x63puhp_enter\x18\xd9\x02 \x01(\x0b\x32&.perfetto.protos.CpuhpEnterFtraceEventH\x00\x12\x42\n\rcpuhp_latency\x18\xda\x02 \x01(\x0b\x32(.perfetto.protos.CpuhpLatencyFtraceEventH\x00\x12G\n\x10\x66\x61strpc_dma_stat\x18\xdb\x02 \x01(\x0b\x32*.perfetto.protos.FastrpcDmaStatFtraceEventH\x00\x12R\n\x16\x64pu_tracing_mark_write\x18\xdc\x02 \x01(\x0b\x32/.perfetto.protos.DpuTracingMarkWriteFtraceEventH\x00\x12R\n\x16g2d_tracing_mark_write\x18\xdd\x02 \x01(\x0b\x32/.perfetto.protos.G2dTracingMarkWriteFtraceEventH\x00\x12T\n\x17mali_tracing_mark_write\x18\xde\x02 \x01(\x0b\x32\x30.perfetto.protos.MaliTracingMarkWriteFtraceEventH\x00\x12\x41\n\rdma_heap_stat\x18\xdf\x02 \x01(\x0b\x32\'.perfetto.protos.DmaHeapStatFtraceEventH\x00\x12>\n\x0b\x63puhp_pause\x18\xe0\x02 \x01(\x0b\x32&.perfetto.protos.CpuhpPauseFtraceEventH\x00\x12G\n\x10sched_pi_setprio\x18\xe1\x02 \x01(\x0b\x32*.perfetto.protos.SchedPiSetprioFtraceEventH\x00\x12\x43\n\x0esde_sde_evtlog\x18\xe2\x02 \x01(\x0b\x32(.perfetto.protos.SdeSdeEvtlogFtraceEventH\x00\x12Q\n\x16sde_sde_perf_calc_crtc\x18\xe3\x02 \x01(\x0b\x32..perfetto.protos.SdeSdePerfCalcCrtcFtraceEventH\x00\x12U\n\x18sde_sde_perf_crtc_update\x18\xe4\x02 \x01(\x0b\x32\x30.perfetto.protos.SdeSdePerfCrtcUpdateFtraceEventH\x00\x12V\n\x19sde_sde_perf_set_qos_luts\x18\xe5\x02 \x01(\x0b\x32\x30.perfetto.protos.SdeSdePerfSetQosLutsFtraceEventH\x00\x12S\n\x17sde_sde_perf_update_bus\x18\xe6\x02 \x01(\x0b\x32/.perfetto.protos.SdeSdePerfUpdateBusFtraceEventH\x00\x12K\n\x12rss_stat_throttled\x18\xe7\x02 \x01(\x0b\x32,.perfetto.protos.RssStatThrottledFtraceEventH\x00\x12I\n\x11netif_receive_skb\x18\xe8\x02 \x01(\x0b\x32+.perfetto.protos.NetifReceiveSkbFtraceEventH\x00\x12?\n\x0cnet_dev_xmit\x18\xe9\x02 \x01(\x0b\x32&.perfetto.protos.NetDevXmitFtraceEventH\x00\x12L\n\x13inet_sock_set_state\x18\xea\x02 \x01(\x0b\x32,.perfetto.protos.InetSockSetStateFtraceEventH\x00\x12K\n\x12tcp_retransmit_skb\x18\xeb\x02 \x01(\x0b\x32,.perfetto.protos.TcpRetransmitSkbFtraceEventH\x00\x12R\n\x16\x63ros_ec_sensorhub_data\x18\xec\x02 \x01(\x0b\x32/.perfetto.protos.CrosEcSensorhubDataFtraceEventH\x00\x12R\n\x16napi_gro_receive_entry\x18\xed\x02 \x01(\x0b\x32/.perfetto.protos.NapiGroReceiveEntryFtraceEventH\x00\x12P\n\x15napi_gro_receive_exit\x18\xee\x02 \x01(\x0b\x32..perfetto.protos.NapiGroReceiveExitFtraceEventH\x00\x12:\n\tkfree_skb\x18\xef\x02 \x01(\x0b\x32$.perfetto.protos.KfreeSkbFtraceEventH\x00\x12G\n\x10kvm_access_fault\x18\xf0\x02 \x01(\x0b\x32*.perfetto.protos.KvmAccessFaultFtraceEventH\x00\x12=\n\x0bkvm_ack_irq\x18\xf1\x02 \x01(\x0b\x32%.perfetto.protos.KvmAckIrqFtraceEventH\x00\x12=\n\x0bkvm_age_hva\x18\xf2\x02 \x01(\x0b\x32%.perfetto.protos.KvmAgeHvaFtraceEventH\x00\x12?\n\x0ckvm_age_page\x18\xf3\x02 \x01(\x0b\x32&.perfetto.protos.KvmAgePageFtraceEventH\x00\x12L\n\x13kvm_arm_clear_debug\x18\xf4\x02 \x01(\x0b\x32,.perfetto.protos.KvmArmClearDebugFtraceEventH\x00\x12J\n\x12kvm_arm_set_dreg32\x18\xf5\x02 \x01(\x0b\x32+.perfetto.protos.KvmArmSetDreg32FtraceEventH\x00\x12J\n\x12kvm_arm_set_regset\x18\xf6\x02 \x01(\x0b\x32+.perfetto.protos.KvmArmSetRegsetFtraceEventH\x00\x12L\n\x13kvm_arm_setup_debug\x18\xf7\x02 \x01(\x0b\x32,.perfetto.protos.KvmArmSetupDebugFtraceEventH\x00\x12:\n\tkvm_entry\x18\xf8\x02 \x01(\x0b\x32$.perfetto.protos.KvmEntryFtraceEventH\x00\x12\x38\n\x08kvm_exit\x18\xf9\x02 \x01(\x0b\x32#.perfetto.protos.KvmExitFtraceEventH\x00\x12\x36\n\x07kvm_fpu\x18\xfa\x02 \x01(\x0b\x32".perfetto.protos.KvmFpuFtraceEventH\x00\x12H\n\x11kvm_get_timer_map\x18\xfb\x02 \x01(\x0b\x32*.perfetto.protos.KvmGetTimerMapFtraceEventH\x00\x12\x45\n\x0fkvm_guest_fault\x18\xfc\x02 \x01(\x0b\x32).perfetto.protos.KvmGuestFaultFtraceEventH\x00\x12J\n\x12kvm_handle_sys_reg\x18\xfd\x02 \x01(\x0b\x32+.perfetto.protos.KvmHandleSysRegFtraceEventH\x00\x12\x41\n\rkvm_hvc_arm64\x18\xfe\x02 \x01(\x0b\x32\'.perfetto.protos.KvmHvcArm64FtraceEventH\x00\x12?\n\x0ckvm_irq_line\x18\xff\x02 \x01(\x0b\x32&.perfetto.protos.KvmIrqLineFtraceEventH\x00\x12\x38\n\x08kvm_mmio\x18\x80\x03 \x01(\x0b\x32#.perfetto.protos.KvmMmioFtraceEventH\x00\x12G\n\x10kvm_mmio_emulate\x18\x81\x03 \x01(\x0b\x32*.perfetto.protos.KvmMmioEmulateFtraceEventH\x00\x12L\n\x13kvm_set_guest_debug\x18\x82\x03 \x01(\x0b\x32,.perfetto.protos.KvmSetGuestDebugFtraceEventH\x00\x12=\n\x0bkvm_set_irq\x18\x83\x03 \x01(\x0b\x32%.perfetto.protos.KvmSetIrqFtraceEventH\x00\x12\x46\n\x10kvm_set_spte_hva\x18\x84\x03 \x01(\x0b\x32).perfetto.protos.KvmSetSpteHvaFtraceEventH\x00\x12H\n\x11kvm_set_way_flush\x18\x85\x03 \x01(\x0b\x32*.perfetto.protos.KvmSetWayFlushFtraceEventH\x00\x12\x43\n\x0ekvm_sys_access\x18\x86\x03 \x01(\x0b\x32(.perfetto.protos.KvmSysAccessFtraceEventH\x00\x12\x46\n\x10kvm_test_age_hva\x18\x87\x03 \x01(\x0b\x32).perfetto.protos.KvmTestAgeHvaFtraceEventH\x00\x12I\n\x11kvm_timer_emulate\x18\x88\x03 \x01(\x0b\x32+.perfetto.protos.KvmTimerEmulateFtraceEventH\x00\x12V\n\x18kvm_timer_hrtimer_expire\x18\x89\x03 \x01(\x0b\x32\x31.perfetto.protos.KvmTimerHrtimerExpireFtraceEventH\x00\x12T\n\x17kvm_timer_restore_state\x18\x8a\x03 \x01(\x0b\x32\x30.perfetto.protos.KvmTimerRestoreStateFtraceEventH\x00\x12N\n\x14kvm_timer_save_state\x18\x8b\x03 \x01(\x0b\x32-.perfetto.protos.KvmTimerSaveStateFtraceEventH\x00\x12N\n\x14kvm_timer_update_irq\x18\x8c\x03 \x01(\x0b\x32-.perfetto.protos.KvmTimerUpdateIrqFtraceEventH\x00\x12G\n\x10kvm_toggle_cache\x18\x8d\x03 \x01(\x0b\x32*.perfetto.protos.KvmToggleCacheFtraceEventH\x00\x12L\n\x13kvm_unmap_hva_range\x18\x8e\x03 \x01(\x0b\x32,.perfetto.protos.KvmUnmapHvaRangeFtraceEventH\x00\x12K\n\x12kvm_userspace_exit\x18\x8f\x03 \x01(\x0b\x32,.perfetto.protos.KvmUserspaceExitFtraceEventH\x00\x12\x45\n\x0fkvm_vcpu_wakeup\x18\x90\x03 \x01(\x0b\x32).perfetto.protos.KvmVcpuWakeupFtraceEventH\x00\x12\x41\n\rkvm_wfx_arm64\x18\x91\x03 \x01(\x0b\x32\'.perfetto.protos.KvmWfxArm64FtraceEventH\x00\x12\x38\n\x08trap_reg\x18\x92\x03 \x01(\x0b\x32#.perfetto.protos.TrapRegFtraceEventH\x00\x12T\n\x17vgic_update_irq_pending\x18\x93\x03 \x01(\x0b\x32\x30.perfetto.protos.VgicUpdateIrqPendingFtraceEventH\x00\x12S\n\x16wakeup_source_activate\x18\x94\x03 \x01(\x0b\x32\x30.perfetto.protos.WakeupSourceActivateFtraceEventH\x00\x12W\n\x18wakeup_source_deactivate\x18\x95\x03 \x01(\x0b\x32\x32.perfetto.protos.WakeupSourceDeactivateFtraceEventH\x00\x12\x44\n\x0eufshcd_command\x18\x96\x03 \x01(\x0b\x32).perfetto.protos.UfshcdCommandFtraceEventH\x00\x12I\n\x11ufshcd_clk_gating\x18\x97\x03 \x01(\x0b\x32+.perfetto.protos.UfshcdClkGatingFtraceEventH\x00\x12\x37\n\x07\x63onsole\x18\x98\x03 \x01(\x0b\x32#.perfetto.protos.ConsoleFtraceEventH\x00\x12G\n\x10\x64rm_vblank_event\x18\x99\x03 \x01(\x0b\x32*.perfetto.protos.DrmVblankEventFtraceEventH\x00\x12Z\n\x1a\x64rm_vblank_event_delivered\x18\x9a\x03 \x01(\x0b\x32\x33.perfetto.protos.DrmVblankEventDeliveredFtraceEventH\x00\x12\x41\n\rdrm_sched_job\x18\x9b\x03 \x01(\x0b\x32\'.perfetto.protos.DrmSchedJobFtraceEventH\x00\x12=\n\x0b\x64rm_run_job\x18\x9c\x03 \x01(\x0b\x32%.perfetto.protos.DrmRunJobFtraceEventH\x00\x12P\n\x15\x64rm_sched_process_job\x18\x9d\x03 \x01(\x0b\x32..perfetto.protos.DrmSchedProcessJobFtraceEventH\x00\x12\x43\n\x0e\x64ma_fence_init\x18\x9e\x03 \x01(\x0b\x32(.perfetto.protos.DmaFenceInitFtraceEventH\x00\x12\x43\n\x0e\x64ma_fence_emit\x18\x9f\x03 \x01(\x0b\x32(.perfetto.protos.DmaFenceEmitFtraceEventH\x00\x12K\n\x12\x64ma_fence_signaled\x18\xa0\x03 \x01(\x0b\x32,.perfetto.protos.DmaFenceSignaledFtraceEventH\x00\x12N\n\x14\x64ma_fence_wait_start\x18\xa1\x03 \x01(\x0b\x32-.perfetto.protos.DmaFenceWaitStartFtraceEventH\x00\x12J\n\x12\x64ma_fence_wait_end\x18\xa2\x03 \x01(\x0b\x32+.perfetto.protos.DmaFenceWaitEndFtraceEventH\x00\x12>\n\x0b\x66\x32\x66s_iostat\x18\xa3\x03 \x01(\x0b\x32&.perfetto.protos.F2fsIostatFtraceEventH\x00\x12M\n\x13\x66\x32\x66s_iostat_latency\x18\xa4\x03 \x01(\x0b\x32-.perfetto.protos.F2fsIostatLatencyFtraceEventH\x00\x12J\n\x12sched_cpu_util_cfs\x18\xa5\x03 \x01(\x0b\x32+.perfetto.protos.SchedCpuUtilCfsFtraceEventH\x00\x12:\n\tv4l2_qbuf\x18\xa6\x03 \x01(\x0b\x32$.perfetto.protos.V4l2QbufFtraceEventH\x00\x12<\n\nv4l2_dqbuf\x18\xa7\x03 \x01(\x0b\x32%.perfetto.protos.V4l2DqbufFtraceEventH\x00\x12J\n\x12vb2_v4l2_buf_queue\x18\xa8\x03 \x01(\x0b\x32+.perfetto.protos.Vb2V4l2BufQueueFtraceEventH\x00\x12H\n\x11vb2_v4l2_buf_done\x18\xa9\x03 \x01(\x0b\x32*.perfetto.protos.Vb2V4l2BufDoneFtraceEventH\x00\x12\x41\n\rvb2_v4l2_qbuf\x18\xaa\x03 \x01(\x0b\x32\'.perfetto.protos.Vb2V4l2QbufFtraceEventH\x00\x12\x43\n\x0evb2_v4l2_dqbuf\x18\xab\x03 \x01(\x0b\x32(.perfetto.protos.Vb2V4l2DqbufFtraceEventH\x00\x12L\n\x13\x64si_cmd_fifo_status\x18\xac\x03 \x01(\x0b\x32,.perfetto.protos.DsiCmdFifoStatusFtraceEventH\x00\x12\x34\n\x06\x64si_rx\x18\xad\x03 \x01(\x0b\x32!.perfetto.protos.DsiRxFtraceEventH\x00\x12\x34\n\x06\x64si_tx\x18\xae\x03 \x01(\x0b\x32!.perfetto.protos.DsiTxFtraceEventH\x00\x12T\n\x17\x61ndroid_fs_dataread_end\x18\xaf\x03 \x01(\x0b\x32\x30.perfetto.protos.AndroidFsDatareadEndFtraceEventH\x00\x12X\n\x19\x61ndroid_fs_dataread_start\x18\xb0\x03 \x01(\x0b\x32\x32.perfetto.protos.AndroidFsDatareadStartFtraceEventH\x00\x12V\n\x18\x61ndroid_fs_datawrite_end\x18\xb1\x03 \x01(\x0b\x32\x31.perfetto.protos.AndroidFsDatawriteEndFtraceEventH\x00\x12Z\n\x1a\x61ndroid_fs_datawrite_start\x18\xb2\x03 \x01(\x0b\x32\x33.perfetto.protos.AndroidFsDatawriteStartFtraceEventH\x00\x12N\n\x14\x61ndroid_fs_fsync_end\x18\xb3\x03 \x01(\x0b\x32-.perfetto.protos.AndroidFsFsyncEndFtraceEventH\x00\x12R\n\x16\x61ndroid_fs_fsync_start\x18\xb4\x03 \x01(\x0b\x32/.perfetto.protos.AndroidFsFsyncStartFtraceEventH\x00\x12\x46\n\x0f\x66uncgraph_entry\x18\xb5\x03 \x01(\x0b\x32*.perfetto.protos.FuncgraphEntryFtraceEventH\x00\x12\x44\n\x0e\x66uncgraph_exit\x18\xb6\x03 \x01(\x0b\x32).perfetto.protos.FuncgraphExitFtraceEventH\x00\x12G\n\x10virtio_video_cmd\x18\xb7\x03 \x01(\x0b\x32*.perfetto.protos.VirtioVideoCmdFtraceEventH\x00\x12P\n\x15virtio_video_cmd_done\x18\xb8\x03 \x01(\x0b\x32..perfetto.protos.VirtioVideoCmdDoneFtraceEventH\x00\x12\\\n\x1bvirtio_video_resource_queue\x18\xb9\x03 \x01(\x0b\x32\x34.perfetto.protos.VirtioVideoResourceQueueFtraceEventH\x00\x12\x65\n virtio_video_resource_queue_done\x18\xba\x03 \x01(\x0b\x32\x38.perfetto.protos.VirtioVideoResourceQueueDoneFtraceEventH\x00\x12N\n\x14mm_shrink_slab_start\x18\xbb\x03 \x01(\x0b\x32-.perfetto.protos.MmShrinkSlabStartFtraceEventH\x00\x12J\n\x12mm_shrink_slab_end\x18\xbc\x03 \x01(\x0b\x32+.perfetto.protos.MmShrinkSlabEndFtraceEventH\x00\x12<\n\ntrusty_smc\x18\xbd\x03 \x01(\x0b\x32%.perfetto.protos.TrustySmcFtraceEventH\x00\x12\x45\n\x0ftrusty_smc_done\x18\xbe\x03 \x01(\x0b\x32).perfetto.protos.TrustySmcDoneFtraceEventH\x00\x12I\n\x11trusty_std_call32\x18\xbf\x03 \x01(\x0b\x32+.perfetto.protos.TrustyStdCall32FtraceEventH\x00\x12R\n\x16trusty_std_call32_done\x18\xc0\x03 \x01(\x0b\x32/.perfetto.protos.TrustyStdCall32DoneFtraceEventH\x00\x12M\n\x13trusty_share_memory\x18\xc1\x03 \x01(\x0b\x32-.perfetto.protos.TrustyShareMemoryFtraceEventH\x00\x12V\n\x18trusty_share_memory_done\x18\xc2\x03 \x01(\x0b\x32\x31.perfetto.protos.TrustyShareMemoryDoneFtraceEventH\x00\x12Q\n\x15trusty_reclaim_memory\x18\xc3\x03 \x01(\x0b\x32/.perfetto.protos.TrustyReclaimMemoryFtraceEventH\x00\x12Z\n\x1atrusty_reclaim_memory_done\x18\xc4\x03 \x01(\x0b\x32\x33.perfetto.protos.TrustyReclaimMemoryDoneFtraceEventH\x00\x12<\n\ntrusty_irq\x18\xc5\x03 \x01(\x0b\x32%.perfetto.protos.TrustyIrqFtraceEventH\x00\x12T\n\x17trusty_ipc_handle_event\x18\xc6\x03 \x01(\x0b\x32\x30.perfetto.protos.TrustyIpcHandleEventFtraceEventH\x00\x12K\n\x12trusty_ipc_connect\x18\xc7\x03 \x01(\x0b\x32,.perfetto.protos.TrustyIpcConnectFtraceEventH\x00\x12R\n\x16trusty_ipc_connect_end\x18\xc8\x03 \x01(\x0b\x32/.perfetto.protos.TrustyIpcConnectEndFtraceEventH\x00\x12G\n\x10trusty_ipc_write\x18\xc9\x03 \x01(\x0b\x32*.perfetto.protos.TrustyIpcWriteFtraceEventH\x00\x12\x45\n\x0ftrusty_ipc_poll\x18\xca\x03 \x01(\x0b\x32).perfetto.protos.TrustyIpcPollFtraceEventH\x00\x12\x45\n\x0ftrusty_ipc_read\x18\xcc\x03 \x01(\x0b\x32).perfetto.protos.TrustyIpcReadFtraceEventH\x00\x12L\n\x13trusty_ipc_read_end\x18\xcd\x03 \x01(\x0b\x32,.perfetto.protos.TrustyIpcReadEndFtraceEventH\x00\x12\x41\n\rtrusty_ipc_rx\x18\xce\x03 \x01(\x0b\x32\'.perfetto.protos.TrustyIpcRxFtraceEventH\x00\x12K\n\x12trusty_enqueue_nop\x18\xd0\x03 \x01(\x0b\x32,.perfetto.protos.TrustyEnqueueNopFtraceEventH\x00\x12\x45\n\x0f\x63ma_alloc_start\x18\xd1\x03 \x01(\x0b\x32).perfetto.protos.CmaAllocStartFtraceEventH\x00\x12\x43\n\x0e\x63ma_alloc_info\x18\xd2\x03 \x01(\x0b\x32(.perfetto.protos.CmaAllocInfoFtraceEventH\x00\x12T\n\x17lwis_tracing_mark_write\x18\xd3\x03 \x01(\x0b\x32\x30.perfetto.protos.LwisTracingMarkWriteFtraceEventH\x00\x12N\n\x14virtio_gpu_cmd_queue\x18\xd4\x03 \x01(\x0b\x32-.perfetto.protos.VirtioGpuCmdQueueFtraceEventH\x00\x12T\n\x17virtio_gpu_cmd_response\x18\xd5\x03 \x01(\x0b\x32\x30.perfetto.protos.VirtioGpuCmdResponseFtraceEventH\x00\x12Q\n\x16mali_mali_KCPU_CQS_SET\x18\xd6\x03 \x01(\x0b\x32..perfetto.protos.MaliMaliKCPUCQSSETFtraceEventH\x00\x12^\n\x1dmali_mali_KCPU_CQS_WAIT_START\x18\xd7\x03 \x01(\x0b\x32\x34.perfetto.protos.MaliMaliKCPUCQSWAITSTARTFtraceEventH\x00\x12Z\n\x1bmali_mali_KCPU_CQS_WAIT_END\x18\xd8\x03 \x01(\x0b\x32\x32.perfetto.protos.MaliMaliKCPUCQSWAITENDFtraceEventH\x00\x12[\n\x1bmali_mali_KCPU_FENCE_SIGNAL\x18\xd9\x03 \x01(\x0b\x32\x33.perfetto.protos.MaliMaliKCPUFENCESIGNALFtraceEventH\x00\x12\x62\n\x1fmali_mali_KCPU_FENCE_WAIT_START\x18\xda\x03 \x01(\x0b\x32\x36.perfetto.protos.MaliMaliKCPUFENCEWAITSTARTFtraceEventH\x00\x12^\n\x1dmali_mali_KCPU_FENCE_WAIT_END\x18\xdb\x03 \x01(\x0b\x32\x34.perfetto.protos.MaliMaliKCPUFENCEWAITENDFtraceEventH\x00\x12:\n\thyp_enter\x18\xdc\x03 \x01(\x0b\x32$.perfetto.protos.HypEnterFtraceEventH\x00\x12\x38\n\x08hyp_exit\x18\xdd\x03 \x01(\x0b\x32#.perfetto.protos.HypExitFtraceEventH\x00\x12<\n\nhost_hcall\x18\xde\x03 \x01(\x0b\x32%.perfetto.protos.HostHcallFtraceEventH\x00\x12\x38\n\x08host_smc\x18\xdf\x03 \x01(\x0b\x32#.perfetto.protos.HostSmcFtraceEventH\x00\x12\x43\n\x0ehost_mem_abort\x18\xe0\x03 \x01(\x0b\x32(.perfetto.protos.HostMemAbortFtraceEventH\x00\x12S\n\x16suspend_resume_minimal\x18\xe1\x03 \x01(\x0b\x32\x30.perfetto.protos.SuspendResumeMinimalFtraceEventH\x00\x12_\n\x1dmali_mali_CSF_INTERRUPT_START\x18\xe2\x03 \x01(\x0b\x32\x35.perfetto.protos.MaliMaliCSFINTERRUPTSTARTFtraceEventH\x00\x12[\n\x1bmali_mali_CSF_INTERRUPT_END\x18\xe3\x03 \x01(\x0b\x32\x33.perfetto.protos.MaliMaliCSFINTERRUPTENDFtraceEventH\x00\x12Z\n\x1asamsung_tracing_mark_write\x18\xe4\x03 \x01(\x0b\x32\x33.perfetto.protos.SamsungTracingMarkWriteFtraceEventH\x00\x12\x44\n\x0e\x62inder_command\x18\xe5\x03 \x01(\x0b\x32).perfetto.protos.BinderCommandFtraceEventH\x00\x12\x42\n\rbinder_return\x18\xe6\x03 \x01(\x0b\x32(.perfetto.protos.BinderReturnFtraceEventH\x00\x12R\n\x16sched_switch_with_ctrs\x18\xe7\x03 \x01(\x0b\x32/.perfetto.protos.SchedSwitchWithCtrsFtraceEventH\x00\x12\x45\n\x0fgpu_work_period\x18\xe8\x03 \x01(\x0b\x32).perfetto.protos.GpuWorkPeriodFtraceEventH\x00\x12<\n\nrpm_status\x18\xe9\x03 \x01(\x0b\x32%.perfetto.protos.RpmStatusFtraceEventH\x00\x12M\n\x13panel_write_generic\x18\xea\x03 \x01(\x0b\x32-.perfetto.protos.PanelWriteGenericFtraceEventH\x00\x12K\n\x12sched_migrate_task\x18\xeb\x03 \x01(\x0b\x32,.perfetto.protos.SchedMigrateTaskFtraceEventH\x00\x12S\n\x17\x64pu_dsi_cmd_fifo_status\x18\xec\x03 \x01(\x0b\x32/.perfetto.protos.DpuDsiCmdFifoStatusFtraceEventH\x00\x12;\n\ndpu_dsi_rx\x18\xed\x03 \x01(\x0b\x32$.perfetto.protos.DpuDsiRxFtraceEventH\x00\x12;\n\ndpu_dsi_tx\x18\xee\x03 \x01(\x0b\x32$.perfetto.protos.DpuDsiTxFtraceEventH\x00\x12K\n\x12\x66\x32\x66s_background_gc\x18\xef\x03 \x01(\x0b\x32,.perfetto.protos.F2fsBackgroundGcFtraceEventH\x00\x12\x41\n\rf2fs_gc_begin\x18\xf0\x03 \x01(\x0b\x32\'.perfetto.protos.F2fsGcBeginFtraceEventH\x00\x12=\n\x0b\x66\x32\x66s_gc_end\x18\xf1\x03 \x01(\x0b\x32%.perfetto.protos.F2fsGcEndFtraceEventH\x00\x12G\n\x10\x66\x61strpc_dma_free\x18\xf2\x03 \x01(\x0b\x32*.perfetto.protos.FastrpcDmaFreeFtraceEventH\x00\x12I\n\x11\x66\x61strpc_dma_alloc\x18\xf3\x03 \x01(\x0b\x32+.perfetto.protos.FastrpcDmaAllocFtraceEventH\x00\x12I\n\x11\x66\x61strpc_dma_unmap\x18\xf4\x03 \x01(\x0b\x32+.perfetto.protos.FastrpcDmaUnmapFtraceEventH\x00\x12\x45\n\x0f\x66\x61strpc_dma_map\x18\xf5\x03 \x01(\x0b\x32).perfetto.protos.FastrpcDmaMapFtraceEventH\x00\x12G\n\x10google_icc_event\x18\xf6\x03 \x01(\x0b\x32*.perfetto.protos.GoogleIccEventFtraceEventH\x00\x12G\n\x10google_irm_event\x18\xf7\x03 \x01(\x0b\x32*.perfetto.protos.GoogleIrmEventFtraceEventH\x00\x12V\n\x18\x64\x65vice_pm_callback_start\x18\xf8\x03 \x01(\x0b\x32\x31.perfetto.protos.DevicePmCallbackStartFtraceEventH\x00\x12R\n\x16\x64\x65vice_pm_callback_end\x18\xf9\x03 \x01(\x0b\x32/.perfetto.protos.DevicePmCallbackEndFtraceEventH\x00\x12V\n\x18thermal_exynos_acpm_bulk\x18\xfa\x03 \x01(\x0b\x32\x31.perfetto.protos.ThermalExynosAcpmBulkFtraceEventH\x00\x12g\n!thermal_exynos_acpm_high_overhead\x18\xfb\x03 \x01(\x0b\x32\x39.perfetto.protos.ThermalExynosAcpmHighOverheadFtraceEventH\x00\x12<\n\ndcvsh_freq\x18\xfc\x03 \x01(\x0b\x32%.perfetto.protos.DcvshFreqFtraceEventH\x00\x12K\n\x12kgsl_gpu_frequency\x18\xfd\x03 \x01(\x0b\x32,.perfetto.protos.KgslGpuFrequencyFtraceEventH\x00\x12\x84\x01\n2mali_mali_PM_MCU_HCTL_CORES_DOWN_SCALE_NOTIFY_PEND\x18\xfe\x03 \x01(\x0b\x32\x45.perfetto.protos.MaliMaliPMMCUHCTLCORESDOWNSCALENOTIFYPENDFtraceEventH\x00\x12p\n\'mali_mali_PM_MCU_HCTL_CORES_NOTIFY_PEND\x18\xff\x03 \x01(\x0b\x32<.perfetto.protos.MaliMaliPMMCUHCTLCORESNOTIFYPENDFtraceEventH\x00\x12r\n(mali_mali_PM_MCU_HCTL_CORE_INACTIVE_PEND\x18\x80\x04 \x01(\x0b\x32=.perfetto.protos.MaliMaliPMMCUHCTLCOREINACTIVEPENDFtraceEventH\x00\x12j\n$mali_mali_PM_MCU_HCTL_MCU_ON_RECHECK\x18\x81\x04 \x01(\x0b\x32\x39.perfetto.protos.MaliMaliPMMCUHCTLMCUONRECHECKFtraceEventH\x00\x12w\n+mali_mali_PM_MCU_HCTL_SHADERS_CORE_OFF_PEND\x18\x82\x04 \x01(\x0b\x32?.perfetto.protos.MaliMaliPMMCUHCTLSHADERSCOREOFFPENDFtraceEventH\x00\x12n\n&mali_mali_PM_MCU_HCTL_SHADERS_PEND_OFF\x18\x83\x04 \x01(\x0b\x32;.perfetto.protos.MaliMaliPMMCUHCTLSHADERSPENDOFFFtraceEventH\x00\x12l\n%mali_mali_PM_MCU_HCTL_SHADERS_PEND_ON\x18\x84\x04 \x01(\x0b\x32:.perfetto.protos.MaliMaliPMMCUHCTLSHADERSPENDONFtraceEventH\x00\x12p\n\'mali_mali_PM_MCU_HCTL_SHADERS_READY_OFF\x18\x85\x04 \x01(\x0b\x32<.perfetto.protos.MaliMaliPMMCUHCTLSHADERSREADYOFFFtraceEventH\x00\x12V\n\x19mali_mali_PM_MCU_IN_SLEEP\x18\x86\x04 \x01(\x0b\x32\x30.perfetto.protos.MaliMaliPMMCUINSLEEPFtraceEventH\x00\x12M\n\x14mali_mali_PM_MCU_OFF\x18\x87\x04 \x01(\x0b\x32,.perfetto.protos.MaliMaliPMMCUOFFFtraceEventH\x00\x12K\n\x13mali_mali_PM_MCU_ON\x18\x88\x04 \x01(\x0b\x32+.perfetto.protos.MaliMaliPMMCUONFtraceEventH\x00\x12s\n)mali_mali_PM_MCU_ON_CORE_ATTR_UPDATE_PEND\x18\x89\x04 \x01(\x0b\x32=.perfetto.protos.MaliMaliPMMCUONCOREATTRUPDATEPENDFtraceEventH\x00\x12h\n#mali_mali_PM_MCU_ON_GLB_REINIT_PEND\x18\x8a\x04 \x01(\x0b\x32\x38.perfetto.protos.MaliMaliPMMCUONGLBREINITPENDFtraceEventH\x00\x12T\n\x18mali_mali_PM_MCU_ON_HALT\x18\x8b\x04 \x01(\x0b\x32/.perfetto.protos.MaliMaliPMMCUONHALTFtraceEventH\x00\x12\x65\n!mali_mali_PM_MCU_ON_HWCNT_DISABLE\x18\x8c\x04 \x01(\x0b\x32\x37.perfetto.protos.MaliMaliPMMCUONHWCNTDISABLEFtraceEventH\x00\x12\x63\n mali_mali_PM_MCU_ON_HWCNT_ENABLE\x18\x8d\x04 \x01(\x0b\x32\x36.perfetto.protos.MaliMaliPMMCUONHWCNTENABLEFtraceEventH\x00\x12]\n\x1dmali_mali_PM_MCU_ON_PEND_HALT\x18\x8e\x04 \x01(\x0b\x32\x33.perfetto.protos.MaliMaliPMMCUONPENDHALTFtraceEventH\x00\x12_\n\x1emali_mali_PM_MCU_ON_PEND_SLEEP\x18\x8f\x04 \x01(\x0b\x32\x34.perfetto.protos.MaliMaliPMMCUONPENDSLEEPFtraceEventH\x00\x12g\n"mali_mali_PM_MCU_ON_SLEEP_INITIATE\x18\x90\x04 \x01(\x0b\x32\x38.perfetto.protos.MaliMaliPMMCUONSLEEPINITIATEFtraceEventH\x00\x12V\n\x19mali_mali_PM_MCU_PEND_OFF\x18\x91\x04 \x01(\x0b\x32\x30.perfetto.protos.MaliMaliPMMCUPENDOFFFtraceEventH\x00\x12\x61\n\x1fmali_mali_PM_MCU_PEND_ON_RELOAD\x18\x92\x04 \x01(\x0b\x32\x35.perfetto.protos.MaliMaliPMMCUPENDONRELOADFtraceEventH\x00\x12Z\n\x1bmali_mali_PM_MCU_POWER_DOWN\x18\x93\x04 \x01(\x0b\x32\x32.perfetto.protos.MaliMaliPMMCUPOWERDOWNFtraceEventH\x00\x12Z\n\x1bmali_mali_PM_MCU_RESET_WAIT\x18\x94\x04 \x01(\x0b\x32\x32.perfetto.protos.MaliMaliPMMCURESETWAITFtraceEventH\x00\x12\x45\n\x0f\x62\x63l_irq_trigger\x18\x95\x04 \x01(\x0b\x32).perfetto.protos.BclIrqTriggerFtraceEventH\x00\x12\\\n\x1bkgsl_adreno_cmdbatch_queued\x18\x96\x04 \x01(\x0b\x32\x34.perfetto.protos.KgslAdrenoCmdbatchQueuedFtraceEventH\x00\x12\x62\n\x1ekgsl_adreno_cmdbatch_submitted\x18\x97\x04 \x01(\x0b\x32\x37.perfetto.protos.KgslAdrenoCmdbatchSubmittedFtraceEventH\x00\x12X\n\x19kgsl_adreno_cmdbatch_sync\x18\x98\x04 \x01(\x0b\x32\x32.perfetto.protos.KgslAdrenoCmdbatchSyncFtraceEventH\x00\x12^\n\x1ckgsl_adreno_cmdbatch_retired\x18\x99\x04 \x01(\x0b\x32\x35.perfetto.protos.KgslAdrenoCmdbatchRetiredFtraceEventH\x00\x12N\n\x14pixel_mm_kswapd_wake\x18\x9a\x04 \x01(\x0b\x32-.perfetto.protos.PixelMmKswapdWakeFtraceEventH\x00\x12N\n\x14pixel_mm_kswapd_done\x18\x9b\x04 \x01(\x0b\x32-.perfetto.protos.PixelMmKswapdDoneFtraceEventH\x00\x12R\n\x16sched_wakeup_task_attr\x18\x9c\x04 \x01(\x0b\x32/.perfetto.protos.SchedWakeupTaskAttrFtraceEventH\x00\x42\x07\n\x05\x65vent"\xc1\x01\n\x0e\x46traceCpuStats\x12\x0b\n\x03\x63pu\x18\x01 \x01(\x04\x12\x0f\n\x07\x65ntries\x18\x02 \x01(\x04\x12\x0f\n\x07overrun\x18\x03 \x01(\x04\x12\x16\n\x0e\x63ommit_overrun\x18\x04 \x01(\x04\x12\x12\n\nbytes_read\x18\x05 \x01(\x04\x12\x17\n\x0foldest_event_ts\x18\x06 \x01(\x01\x12\x0e\n\x06now_ts\x18\x07 \x01(\x01\x12\x16\n\x0e\x64ropped_events\x18\x08 \x01(\x04\x12\x13\n\x0bread_events\x18\t \x01(\x04"\xa7\x03\n\x0b\x46traceStats\x12\x31\n\x05phase\x18\x01 \x01(\x0e\x32".perfetto.protos.FtraceStats.Phase\x12\x32\n\tcpu_stats\x18\x02 \x03(\x0b\x32\x1f.perfetto.protos.FtraceCpuStats\x12\x1d\n\x15kernel_symbols_parsed\x18\x03 \x01(\r\x12\x1d\n\x15kernel_symbols_mem_kb\x18\x04 \x01(\r\x12\x15\n\ratrace_errors\x18\x05 \x01(\t\x12\x1d\n\x15unknown_ftrace_events\x18\x06 \x03(\t\x12\x1c\n\x14\x66\x61iled_ftrace_events\x18\x07 \x03(\t\x12\x1e\n\x16preserve_ftrace_buffer\x18\x08 \x01(\x08\x12?\n\x13\x66trace_parse_errors\x18\t \x03(\x0e\x32".perfetto.protos.FtraceParseStatus">\n\x05Phase\x12\x0f\n\x0bUNSPECIFIED\x10\x00\x12\x12\n\x0eSTART_OF_TRACE\x10\x01\x12\x10\n\x0c\x45ND_OF_TRACE\x10\x02"\xe0\x06\n\x11\x46traceEventBundle\x12\x0b\n\x03\x63pu\x18\x01 \x01(\r\x12+\n\x05\x65vent\x18\x02 \x03(\x0b\x32\x1c.perfetto.protos.FtraceEvent\x12\x13\n\x0blost_events\x18\x03 \x01(\x08\x12\x46\n\rcompact_sched\x18\x04 \x01(\x0b\x32/.perfetto.protos.FtraceEventBundle.CompactSched\x12\x32\n\x0c\x66trace_clock\x18\x05 \x01(\x0e\x32\x1c.perfetto.protos.FtraceClock\x12\x18\n\x10\x66trace_timestamp\x18\x06 \x01(\x03\x12\x16\n\x0e\x62oot_timestamp\x18\x07 \x01(\x03\x12=\n\x05\x65rror\x18\x08 \x03(\x0b\x32..perfetto.protos.FtraceEventBundle.FtraceError\x12!\n\x19last_read_event_timestamp\x18\t \x01(\x04\x12%\n\x1dprevious_bundle_end_timestamp\x18\n \x01(\x04\x1a\xee\x02\n\x0c\x43ompactSched\x12\x14\n\x0cintern_table\x18\x05 \x03(\t\x12\x1c\n\x10switch_timestamp\x18\x01 \x03(\x04\x42\x02\x10\x01\x12\x1d\n\x11switch_prev_state\x18\x02 \x03(\x03\x42\x02\x10\x01\x12\x1b\n\x0fswitch_next_pid\x18\x03 \x03(\x05\x42\x02\x10\x01\x12\x1c\n\x10switch_next_prio\x18\x04 \x03(\x05\x42\x02\x10\x01\x12"\n\x16switch_next_comm_index\x18\x06 \x03(\rB\x02\x10\x01\x12\x1c\n\x10waking_timestamp\x18\x07 \x03(\x04\x42\x02\x10\x01\x12\x16\n\nwaking_pid\x18\x08 \x03(\x05\x42\x02\x10\x01\x12\x1d\n\x11waking_target_cpu\x18\t \x03(\x05\x42\x02\x10\x01\x12\x17\n\x0bwaking_prio\x18\n \x03(\x05\x42\x02\x10\x01\x12\x1d\n\x11waking_comm_index\x18\x0b \x03(\rB\x02\x10\x01\x12\x1f\n\x13waking_common_flags\x18\x0c \x03(\rB\x02\x10\x01\x1aT\n\x0b\x46traceError\x12\x11\n\ttimestamp\x18\x01 \x01(\x04\x12\x32\n\x06status\x18\x02 \x01(\x0e\x32".perfetto.protos.FtraceParseStatus"\xfb\x01\n\x0fGpuCounterEvent\x12\x41\n\x12\x63ounter_descriptor\x18\x01 \x01(\x0b\x32%.perfetto.protos.GpuCounterDescriptor\x12=\n\x08\x63ounters\x18\x02 \x03(\x0b\x32+.perfetto.protos.GpuCounterEvent.GpuCounter\x12\x0e\n\x06gpu_id\x18\x03 \x01(\x05\x1aV\n\nGpuCounter\x12\x12\n\ncounter_id\x18\x01 \x01(\r\x12\x13\n\tint_value\x18\x02 \x01(\x03H\x00\x12\x16\n\x0c\x64ouble_value\x18\x03 \x01(\x01H\x00\x42\x07\n\x05value"\x84\x02\n\x06GpuLog\x12\x32\n\x08severity\x18\x01 \x01(\x0e\x32 .perfetto.protos.GpuLog.Severity\x12\x0b\n\x03tag\x18\x02 \x01(\t\x12\x13\n\x0blog_message\x18\x03 \x01(\t"\xa3\x01\n\x08Severity\x12\x1c\n\x18LOG_SEVERITY_UNSPECIFIED\x10\x00\x12\x18\n\x14LOG_SEVERITY_VERBOSE\x10\x01\x12\x16\n\x12LOG_SEVERITY_DEBUG\x10\x02\x12\x15\n\x11LOG_SEVERITY_INFO\x10\x03\x12\x18\n\x14LOG_SEVERITY_WARNING\x10\x04\x12\x16\n\x12LOG_SEVERITY_ERROR\x10\x05"\xf6\x06\n\x13GpuRenderStageEvent\x12\x10\n\x08\x65vent_id\x18\x01 \x01(\x04\x12\x10\n\x08\x64uration\x18\x02 \x01(\x04\x12\x14\n\x0chw_queue_iid\x18\r \x01(\x04\x12\x11\n\tstage_iid\x18\x0e \x01(\x04\x12\x0e\n\x06gpu_id\x18\x0b \x01(\x05\x12\x0f\n\x07\x63ontext\x18\x05 \x01(\x04\x12\x1c\n\x14render_target_handle\x18\x08 \x01(\x04\x12\x15\n\rsubmission_id\x18\n \x01(\r\x12\x42\n\nextra_data\x18\x06 \x03(\x0b\x32..perfetto.protos.GpuRenderStageEvent.ExtraData\x12\x1a\n\x12render_pass_handle\x18\t \x01(\x04\x12!\n\x19render_subpass_index_mask\x18\x0f \x03(\x04\x12\x1d\n\x15\x63ommand_buffer_handle\x18\x0c \x01(\x04\x12O\n\x0especifications\x18\x07 \x01(\x0b\x32\x33.perfetto.protos.GpuRenderStageEvent.SpecificationsB\x02\x18\x01\x12\x17\n\x0bhw_queue_id\x18\x03 \x01(\x05\x42\x02\x18\x01\x12\x14\n\x08stage_id\x18\x04 \x01(\x05\x42\x02\x18\x01\x1a(\n\tExtraData\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t\x1a\xe9\x02\n\x0eSpecifications\x12U\n\x0c\x63ontext_spec\x18\x01 \x01(\x0b\x32?.perfetto.protos.GpuRenderStageEvent.Specifications.ContextSpec\x12Q\n\x08hw_queue\x18\x02 \x03(\x0b\x32?.perfetto.protos.GpuRenderStageEvent.Specifications.Description\x12N\n\x05stage\x18\x03 \x03(\x0b\x32?.perfetto.protos.GpuRenderStageEvent.Specifications.Description\x1a+\n\x0b\x43ontextSpec\x12\x0f\n\x07\x63ontext\x18\x01 \x01(\x04\x12\x0b\n\x03pid\x18\x02 \x01(\x05\x1a\x30\n\x0b\x44\x65scription\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x13\n\x0b\x64\x65scription\x18\x02 \x01(\t*\x04\x08\x64\x10\x65"\xaa\x01\n\x17InternedGraphicsContext\x12\x0b\n\x03iid\x18\x01 \x01(\x04\x12\x0b\n\x03pid\x18\x02 \x01(\x05\x12\x39\n\x03\x61pi\x18\x03 \x01(\x0e\x32,.perfetto.protos.InternedGraphicsContext.Api":\n\x03\x41pi\x12\r\n\tUNDEFINED\x10\x00\x12\x0b\n\x07OPEN_GL\x10\x01\x12\n\n\x06VULKAN\x10\x02\x12\x0b\n\x07OPEN_CL\x10\x03"\xee\x01\n#InternedGpuRenderStageSpecification\x12\x0b\n\x03iid\x18\x01 \x01(\x04\x12\x0c\n\x04name\x18\x02 \x01(\t\x12\x13\n\x0b\x64\x65scription\x18\x03 \x01(\t\x12Z\n\x08\x63\x61tegory\x18\x04 \x01(\x0e\x32H.perfetto.protos.InternedGpuRenderStageSpecification.RenderStageCategory";\n\x13RenderStageCategory\x12\t\n\x05OTHER\x10\x00\x12\x0c\n\x08GRAPHICS\x10\x01\x12\x0b\n\x07\x43OMPUTE\x10\x02"\xbb\x03\n\x0eVulkanApiEvent\x12\\\n\x1avk_debug_utils_object_name\x18\x01 \x01(\x0b\x32\x36.perfetto.protos.VulkanApiEvent.VkDebugUtilsObjectNameH\x00\x12H\n\x0fvk_queue_submit\x18\x02 \x01(\x0b\x32-.perfetto.protos.VulkanApiEvent.VkQueueSubmitH\x00\x1ar\n\x16VkDebugUtilsObjectName\x12\x0b\n\x03pid\x18\x01 \x01(\r\x12\x11\n\tvk_device\x18\x02 \x01(\x04\x12\x13\n\x0bobject_type\x18\x03 \x01(\x05\x12\x0e\n\x06object\x18\x04 \x01(\x04\x12\x13\n\x0bobject_name\x18\x05 \x01(\t\x1a\x83\x01\n\rVkQueueSubmit\x12\x13\n\x0b\x64uration_ns\x18\x01 \x01(\x04\x12\x0b\n\x03pid\x18\x02 \x01(\r\x12\x0b\n\x03tid\x18\x03 \x01(\r\x12\x10\n\x08vk_queue\x18\x04 \x01(\x04\x12\x1a\n\x12vk_command_buffers\x18\x05 \x03(\x04\x12\x15\n\rsubmission_id\x18\x06 \x01(\rB\x07\n\x05\x65vent"z\n\x1bVulkanMemoryEventAnnotation\x12\x0f\n\x07key_iid\x18\x01 \x01(\x04\x12\x13\n\tint_value\x18\x02 \x01(\x03H\x00\x12\x16\n\x0c\x64ouble_value\x18\x03 \x01(\x01H\x00\x12\x14\n\nstring_iid\x18\x04 \x01(\x04H\x00\x42\x07\n\x05value"\xe8\x06\n\x11VulkanMemoryEvent\x12\x39\n\x06source\x18\x01 \x01(\x0e\x32).perfetto.protos.VulkanMemoryEvent.Source\x12?\n\toperation\x18\x02 \x01(\x0e\x32,.perfetto.protos.VulkanMemoryEvent.Operation\x12\x11\n\ttimestamp\x18\x03 \x01(\x03\x12\x0b\n\x03pid\x18\x04 \x01(\r\x12\x16\n\x0ememory_address\x18\x05 \x01(\x06\x12\x13\n\x0bmemory_size\x18\x06 \x01(\x04\x12\x12\n\ncaller_iid\x18\x07 \x01(\x04\x12L\n\x10\x61llocation_scope\x18\x08 \x01(\x0e\x32\x32.perfetto.protos.VulkanMemoryEvent.AllocationScope\x12\x41\n\x0b\x61nnotations\x18\t \x03(\x0b\x32,.perfetto.protos.VulkanMemoryEventAnnotation\x12\x0e\n\x06\x64\x65vice\x18\x10 \x01(\x06\x12\x15\n\rdevice_memory\x18\x11 \x01(\x06\x12\x13\n\x0bmemory_type\x18\x12 \x01(\r\x12\x0c\n\x04heap\x18\x13 \x01(\r\x12\x15\n\robject_handle\x18\x14 \x01(\x06"\x85\x01\n\x06Source\x12\x16\n\x12SOURCE_UNSPECIFIED\x10\x00\x12\x11\n\rSOURCE_DRIVER\x10\x01\x12\x11\n\rSOURCE_DEVICE\x10\x02\x12\x18\n\x14SOURCE_DEVICE_MEMORY\x10\x03\x12\x11\n\rSOURCE_BUFFER\x10\x04\x12\x10\n\x0cSOURCE_IMAGE\x10\x05"u\n\tOperation\x12\x12\n\x0eOP_UNSPECIFIED\x10\x00\x12\r\n\tOP_CREATE\x10\x01\x12\x0e\n\nOP_DESTROY\x10\x02\x12\x0b\n\x07OP_BIND\x10\x03\x12\x14\n\x10OP_DESTROY_BOUND\x10\x04\x12\x12\n\x0eOP_ANNOTATIONS\x10\x05"\x84\x01\n\x0f\x41llocationScope\x12\x15\n\x11SCOPE_UNSPECIFIED\x10\x00\x12\x11\n\rSCOPE_COMMAND\x10\x01\x12\x10\n\x0cSCOPE_OBJECT\x10\x02\x12\x0f\n\x0bSCOPE_CACHE\x10\x03\x12\x10\n\x0cSCOPE_DEVICE\x10\x04\x12\x12\n\x0eSCOPE_INSTANCE\x10\x05"*\n\x0eInternedString\x12\x0b\n\x03iid\x18\x01 \x01(\x04\x12\x0b\n\x03str\x18\x02 \x01(\x0c"n\n\x14ProfiledFrameSymbols\x12\x11\n\tframe_iid\x18\x01 \x01(\x04\x12\x18\n\x10\x66unction_name_id\x18\x02 \x03(\x04\x12\x14\n\x0c\x66ile_name_id\x18\x03 \x03(\x04\x12\x13\n\x0bline_number\x18\x04 \x03(\r"L\n\x04Line\x12\x15\n\rfunction_name\x18\x01 \x01(\t\x12\x18\n\x10source_file_name\x18\x02 \x01(\t\x12\x13\n\x0bline_number\x18\x03 \x01(\r"G\n\x0e\x41\x64\x64ressSymbols\x12\x0f\n\x07\x61\x64\x64ress\x18\x01 \x01(\x04\x12$\n\x05lines\x18\x02 \x03(\x0b\x32\x15.perfetto.protos.Line"i\n\rModuleSymbols\x12\x0c\n\x04path\x18\x01 \x01(\t\x12\x10\n\x08\x62uild_id\x18\x02 \x01(\t\x12\x38\n\x0f\x61\x64\x64ress_symbols\x18\x03 \x03(\x0b\x32\x1f.perfetto.protos.AddressSymbols"\x9c\x01\n\x07Mapping\x12\x0b\n\x03iid\x18\x01 \x01(\x04\x12\x10\n\x08\x62uild_id\x18\x02 \x01(\x04\x12\x14\n\x0c\x65xact_offset\x18\x08 \x01(\x04\x12\x14\n\x0cstart_offset\x18\x03 \x01(\x04\x12\r\n\x05start\x18\x04 \x01(\x04\x12\x0b\n\x03\x65nd\x18\x05 \x01(\x04\x12\x11\n\tload_bias\x18\x06 \x01(\x04\x12\x17\n\x0fpath_string_ids\x18\x07 \x03(\x04"R\n\x05\x46rame\x12\x0b\n\x03iid\x18\x01 \x01(\x04\x12\x18\n\x10\x66unction_name_id\x18\x02 \x01(\x04\x12\x12\n\nmapping_id\x18\x03 \x01(\x04\x12\x0e\n\x06rel_pc\x18\x04 \x01(\x04"+\n\tCallstack\x12\x0b\n\x03iid\x18\x01 \x01(\x04\x12\x11\n\tframe_ids\x18\x02 \x03(\x04"*\n\rHistogramName\x12\x0b\n\x03iid\x18\x01 \x01(\x04\x12\x0c\n\x04name\x18\x02 \x01(\t"Z\n\x15\x43hromeHistogramSample\x12\x11\n\tname_hash\x18\x01 \x01(\x04\x12\x0c\n\x04name\x18\x02 \x01(\t\x12\x0e\n\x06sample\x18\x03 \x01(\x03\x12\x10\n\x08name_iid\x18\x04 \x01(\x04"\xac\x07\n\x0f\x44\x65\x62ugAnnotation\x12\x12\n\x08name_iid\x18\x01 \x01(\x04H\x00\x12\x0e\n\x04name\x18\n \x01(\tH\x00\x12\x14\n\nbool_value\x18\x02 \x01(\x08H\x01\x12\x14\n\nuint_value\x18\x03 \x01(\x04H\x01\x12\x13\n\tint_value\x18\x04 \x01(\x03H\x01\x12\x16\n\x0c\x64ouble_value\x18\x05 \x01(\x01H\x01\x12\x17\n\rpointer_value\x18\x07 \x01(\x04H\x01\x12\x44\n\x0cnested_value\x18\x08 \x01(\x0b\x32,.perfetto.protos.DebugAnnotation.NestedValueH\x01\x12\x1b\n\x11legacy_json_value\x18\t \x01(\tH\x01\x12\x16\n\x0cstring_value\x18\x06 \x01(\tH\x01\x12\x1a\n\x10string_value_iid\x18\x11 \x01(\x04H\x01\x12\x19\n\x0fproto_type_name\x18\x10 \x01(\tH\x02\x12\x1d\n\x13proto_type_name_iid\x18\r \x01(\x04H\x02\x12\x13\n\x0bproto_value\x18\x0e \x01(\x0c\x12\x36\n\x0c\x64ict_entries\x18\x0b \x03(\x0b\x32 .perfetto.protos.DebugAnnotation\x12\x36\n\x0c\x61rray_values\x18\x0c \x03(\x0b\x32 .perfetto.protos.DebugAnnotation\x1a\xfc\x02\n\x0bNestedValue\x12L\n\x0bnested_type\x18\x01 \x01(\x0e\x32\x37.perfetto.protos.DebugAnnotation.NestedValue.NestedType\x12\x11\n\tdict_keys\x18\x02 \x03(\t\x12\x41\n\x0b\x64ict_values\x18\x03 \x03(\x0b\x32,.perfetto.protos.DebugAnnotation.NestedValue\x12\x42\n\x0c\x61rray_values\x18\x04 \x03(\x0b\x32,.perfetto.protos.DebugAnnotation.NestedValue\x12\x11\n\tint_value\x18\x05 \x01(\x03\x12\x14\n\x0c\x64ouble_value\x18\x06 \x01(\x01\x12\x12\n\nbool_value\x18\x07 \x01(\x08\x12\x14\n\x0cstring_value\x18\x08 \x01(\t"2\n\nNestedType\x12\x0f\n\x0bUNSPECIFIED\x10\x00\x12\x08\n\x04\x44ICT\x10\x01\x12\t\n\x05\x41RRAY\x10\x02\x42\x0c\n\nname_fieldB\x07\n\x05valueB\x17\n\x15proto_type_descriptor"0\n\x13\x44\x65\x62ugAnnotationName\x12\x0b\n\x03iid\x18\x01 \x01(\x04\x12\x0c\n\x04name\x18\x02 \x01(\t"9\n\x1c\x44\x65\x62ugAnnotationValueTypeName\x12\x0b\n\x03iid\x18\x01 \x01(\x04\x12\x0c\n\x04name\x18\x02 \x01(\t"\x83\x02\n\nLogMessage\x12\x1b\n\x13source_location_iid\x18\x01 \x01(\x04\x12\x10\n\x08\x62ody_iid\x18\x02 \x01(\x04\x12\x32\n\x04prio\x18\x03 \x01(\x0e\x32$.perfetto.protos.LogMessage.Priority"\x91\x01\n\x08Priority\x12\x14\n\x10PRIO_UNSPECIFIED\x10\x00\x12\x0f\n\x0bPRIO_UNUSED\x10\x01\x12\x10\n\x0cPRIO_VERBOSE\x10\x02\x12\x0e\n\nPRIO_DEBUG\x10\x03\x12\r\n\tPRIO_INFO\x10\x04\x12\r\n\tPRIO_WARN\x10\x05\x12\x0e\n\nPRIO_ERROR\x10\x06\x12\x0e\n\nPRIO_FATAL\x10\x07"+\n\x0eLogMessageBody\x12\x0b\n\x03iid\x18\x01 \x01(\x04\x12\x0c\n\x04\x62ody\x18\x02 \x01(\t"M\n\x1aUnsymbolizedSourceLocation\x12\x0b\n\x03iid\x18\x01 \x01(\x04\x12\x12\n\nmapping_id\x18\x02 \x01(\x04\x12\x0e\n\x06rel_pc\x18\x03 \x01(\x04"\\\n\x0eSourceLocation\x12\x0b\n\x03iid\x18\x01 \x01(\x04\x12\x11\n\tfile_name\x18\x02 \x01(\t\x12\x15\n\rfunction_name\x18\x03 \x01(\t\x12\x13\n\x0bline_number\x18\x04 \x01(\r"$\n\x15\x43hromeActiveProcesses\x12\x0b\n\x03pid\x18\x01 \x03(\x05"\xee\x02\n\x1a\x43hromeApplicationStateInfo\x12]\n\x11\x61pplication_state\x18\x01 \x01(\x0e\x32\x42.perfetto.protos.ChromeApplicationStateInfo.ChromeApplicationState"\xf0\x01\n\x16\x43hromeApplicationState\x12\x1d\n\x19\x41PPLICATION_STATE_UNKNOWN\x10\x00\x12,\n(APPLICATION_STATE_HAS_RUNNING_ACTIVITIES\x10\x01\x12+\n\'APPLICATION_STATE_HAS_PAUSED_ACTIVITIES\x10\x02\x12,\n(APPLICATION_STATE_HAS_STOPPED_ACTIVITIES\x10\x03\x12.\n*APPLICATION_STATE_HAS_DESTROYED_ACTIVITIES\x10\x04"\xbf\x08\n\x1e\x43hromeCompositorSchedulerState\x12\x44\n\rstate_machine\x18\x01 \x01(\x0b\x32-.perfetto.protos.ChromeCompositorStateMachine\x12$\n\x1cobserving_begin_frame_source\x18\x02 \x01(\x08\x12&\n\x1e\x62\x65gin_impl_frame_deadline_task\x18\x03 \x01(\x08\x12 \n\x18pending_begin_frame_task\x18\x04 \x01(\x08\x12\x33\n+skipped_last_frame_missed_exceeded_deadline\x18\x05 \x01(\x08\x12G\n\rinside_action\x18\x07 \x01(\x0e\x32\x30.perfetto.protos.ChromeCompositorSchedulerAction\x12\x61\n\rdeadline_mode\x18\x08 \x01(\x0e\x32J.perfetto.protos.ChromeCompositorSchedulerState.BeginImplFrameDeadlineMode\x12\x13\n\x0b\x64\x65\x61\x64line_us\x18\t \x01(\x03\x12 \n\x18\x64\x65\x61\x64line_scheduled_at_us\x18\n \x01(\x03\x12\x0e\n\x06now_us\x18\x0b \x01(\x03\x12 \n\x18now_to_deadline_delta_us\x18\x0c \x01(\x03\x12-\n%now_to_deadline_scheduled_at_delta_us\x18\r \x01(\x03\x12\x42\n\x15\x62\x65gin_impl_frame_args\x18\x0e \x01(\x0b\x32#.perfetto.protos.BeginImplFrameArgs\x12L\n\x1a\x62\x65gin_frame_observer_state\x18\x0f \x01(\x0b\x32(.perfetto.protos.BeginFrameObserverState\x12H\n\x18\x62\x65gin_frame_source_state\x18\x10 \x01(\x0b\x32&.perfetto.protos.BeginFrameSourceState\x12K\n\x19\x63ompositor_timing_history\x18\x11 \x01(\x0b\x32(.perfetto.protos.CompositorTimingHistory"\xbe\x01\n\x1a\x42\x65ginImplFrameDeadlineMode\x12\x1d\n\x19\x44\x45\x41\x44LINE_MODE_UNSPECIFIED\x10\x00\x12\x16\n\x12\x44\x45\x41\x44LINE_MODE_NONE\x10\x01\x12\x1b\n\x17\x44\x45\x41\x44LINE_MODE_IMMEDIATE\x10\x02\x12\x19\n\x15\x44\x45\x41\x44LINE_MODE_REGULAR\x10\x03\x12\x16\n\x12\x44\x45\x41\x44LINE_MODE_LATE\x10\x04\x12\x19\n\x15\x44\x45\x41\x44LINE_MODE_BLOCKED\x10\x05J\x04\x08\x06\x10\x07"\xfe\x1c\n\x1c\x43hromeCompositorStateMachine\x12M\n\x0bmajor_state\x18\x01 \x01(\x0b\x32\x38.perfetto.protos.ChromeCompositorStateMachine.MajorState\x12M\n\x0bminor_state\x18\x02 \x01(\x0b\x32\x38.perfetto.protos.ChromeCompositorStateMachine.MinorState\x1a\x93\n\n\nMajorState\x12\x45\n\x0bnext_action\x18\x01 \x01(\x0e\x32\x30.perfetto.protos.ChromeCompositorSchedulerAction\x12l\n\x16\x62\x65gin_impl_frame_state\x18\x02 \x01(\x0e\x32L.perfetto.protos.ChromeCompositorStateMachine.MajorState.BeginImplFrameState\x12l\n\x16\x62\x65gin_main_frame_state\x18\x03 \x01(\x0e\x32L.perfetto.protos.ChromeCompositorStateMachine.MajorState.BeginMainFrameState\x12u\n\x1blayer_tree_frame_sink_state\x18\x04 \x01(\x0e\x32P.perfetto.protos.ChromeCompositorStateMachine.MajorState.LayerTreeFrameSinkState\x12p\n\x13\x66orced_redraw_state\x18\x05 \x01(\x0e\x32S.perfetto.protos.ChromeCompositorStateMachine.MajorState.ForcedRedrawOnTimeoutState"\xa1\x01\n\x13\x42\x65ginImplFrameState\x12 \n\x1c\x42\x45GIN_IMPL_FRAME_UNSPECIFIED\x10\x00\x12\x19\n\x15\x42\x45GIN_IMPL_FRAME_IDLE\x10\x01\x12\'\n#BEGIN_IMPL_FRAME_INSIDE_BEGIN_FRAME\x10\x02\x12$\n BEGIN_IMPL_FRAME_INSIDE_DEADLINE\x10\x03"\x93\x01\n\x13\x42\x65ginMainFrameState\x12 \n\x1c\x42\x45GIN_MAIN_FRAME_UNSPECIFIED\x10\x00\x12\x19\n\x15\x42\x45GIN_MAIN_FRAME_IDLE\x10\x01\x12\x19\n\x15\x42\x45GIN_MAIN_FRAME_SENT\x10\x02\x12$\n BEGIN_MAIN_FRAME_READY_TO_COMMIT\x10\x03"\xf4\x01\n\x17LayerTreeFrameSinkState\x12 \n\x1cLAYER_TREE_FRAME_UNSPECIFIED\x10\x00\x12\x19\n\x15LAYER_TREE_FRAME_NONE\x10\x01\x12\x1b\n\x17LAYER_TREE_FRAME_ACTIVE\x10\x02\x12\x1d\n\x19LAYER_TREE_FRAME_CREATING\x10\x03\x12-\n)LAYER_TREE_FRAME_WAITING_FOR_FIRST_COMMIT\x10\x04\x12\x31\n-LAYER_TREE_FRAME_WAITING_FOR_FIRST_ACTIVATION\x10\x05"\xc7\x01\n\x1a\x46orcedRedrawOnTimeoutState\x12\x1d\n\x19\x46ORCED_REDRAW_UNSPECIFIED\x10\x00\x12\x16\n\x12\x46ORCED_REDRAW_IDLE\x10\x01\x12$\n FORCED_REDRAW_WAITING_FOR_COMMIT\x10\x02\x12(\n$FORCED_REDRAW_WAITING_FOR_ACTIVATION\x10\x03\x12"\n\x1e\x46ORCED_REDRAW_WAITING_FOR_DRAW\x10\x04\x1a\xa9\x11\n\nMinorState\x12\x14\n\x0c\x63ommit_count\x18\x01 \x01(\x05\x12\x1c\n\x14\x63urrent_frame_number\x18\x02 \x01(\x05\x12*\n"last_frame_number_submit_performed\x18\x03 \x01(\x05\x12(\n last_frame_number_draw_performed\x18\x04 \x01(\x05\x12/\n\'last_frame_number_begin_main_frame_sent\x18\x05 \x01(\x05\x12\x10\n\x08\x64id_draw\x18\x06 \x01(\x08\x12\x33\n+did_send_begin_main_frame_for_current_frame\x18\x07 \x01(\x08\x12\x36\n.did_notify_begin_main_frame_not_expected_until\x18\x08 \x01(\x08\x12\x35\n-did_notify_begin_main_frame_not_expected_soon\x18\t \x01(\x08\x12+\n#wants_begin_main_frame_not_expected\x18\n \x01(\x08\x12\x1f\n\x17\x64id_commit_during_frame\x18\x0b \x01(\x08\x12,\n$did_invalidate_layer_tree_frame_sink\x18\x0c \x01(\x08\x12)\n!did_perform_impl_side_invalidaion\x18\r \x01(\x08\x12\x19\n\x11\x64id_prepare_tiles\x18\x0e \x01(\x08\x12+\n#consecutive_checkerboard_animations\x18\x0f \x01(\x05\x12\x1d\n\x15pending_submit_frames\x18\x10 \x01(\x05\x12\x38\n0submit_frames_with_current_layer_tree_frame_sink\x18\x11 \x01(\x05\x12\x14\n\x0cneeds_redraw\x18\x12 \x01(\x08\x12\x1b\n\x13needs_prepare_tiles\x18\x13 \x01(\x08\x12\x1e\n\x16needs_begin_main_frame\x18\x14 \x01(\x08\x12"\n\x1aneeds_one_begin_impl_frame\x18\x15 \x01(\x08\x12\x0f\n\x07visible\x18\x16 \x01(\x08\x12!\n\x19\x62\x65gin_frame_source_paused\x18\x17 \x01(\x08\x12\x10\n\x08\x63\x61n_draw\x18\x18 \x01(\x08\x12\x19\n\x11resourceless_draw\x18\x19 \x01(\x08\x12\x18\n\x10has_pending_tree\x18\x1a \x01(\x08\x12,\n$pending_tree_is_ready_for_activation\x18\x1b \x01(\x08\x12$\n\x1c\x61\x63tive_tree_needs_first_draw\x18\x1c \x01(\x08\x12$\n\x1c\x61\x63tive_tree_is_ready_to_draw\x18\x1d \x01(\x08\x12=\n5did_create_and_initialize_first_layer_tree_frame_sink\x18\x1e \x01(\x08\x12\\\n\rtree_priority\x18\x1f \x01(\x0e\x32\x45.perfetto.protos.ChromeCompositorStateMachine.MinorState.TreePriority\x12i\n\x14scroll_handler_state\x18 \x01(\x0e\x32K.perfetto.protos.ChromeCompositorStateMachine.MinorState.ScrollHandlerState\x12\x35\n-critical_begin_main_frame_to_activate_is_fast\x18! \x01(\x08\x12(\n main_thread_missed_last_deadline\x18" \x01(\x08\x12 \n\x18video_needs_begin_frames\x18$ \x01(\x08\x12\x1e\n\x16\x64\x65\x66\x65r_begin_main_frame\x18% \x01(\x08\x12"\n\x1alast_commit_had_no_updates\x18& \x01(\x08\x12\x1e\n\x16\x64id_draw_in_last_frame\x18\' \x01(\x08\x12 \n\x18\x64id_submit_in_last_frame\x18( \x01(\x08\x12$\n\x1cneeds_impl_side_invalidation\x18) \x01(\x08\x12)\n!current_pending_tree_is_impl_side\x18* \x01(\x08\x12+\n#previous_pending_tree_was_impl_side\x18+ \x01(\x08\x12\x35\n-processing_animation_worklets_for_active_tree\x18, \x01(\x08\x12\x36\n.processing_animation_worklets_for_pending_tree\x18- \x01(\x08\x12\x32\n*processing_paint_worklets_for_pending_tree\x18. \x01(\x08"\xb8\x01\n\x0cTreePriority\x12\x1d\n\x19TREE_PRIORITY_UNSPECIFIED\x10\x00\x12.\n*TREE_PRIORITY_SAME_PRIORITY_FOR_BOTH_TREES\x10\x01\x12+\n\'TREE_PRIORITY_SMOOTHNESS_TAKES_PRIORITY\x10\x02\x12,\n(TREE_PRIORITY_NEW_CONTENT_TAKES_PRIORITY\x10\x03"\x82\x01\n\x12ScrollHandlerState\x12\x1e\n\x1aSCROLL_HANDLER_UNSPECIFIED\x10\x00\x12!\n\x1dSCROLL_AFFECTS_SCROLL_HANDLER\x10\x01\x12)\n%SCROLL_DOES_NOT_AFFECT_SCROLL_HANDLER\x10\x02J\x04\x08#\x10$"\xaa\x04\n\x0e\x42\x65ginFrameArgs\x12@\n\x04type\x18\x01 \x01(\x0e\x32\x32.perfetto.protos.BeginFrameArgs.BeginFrameArgsType\x12\x11\n\tsource_id\x18\x02 \x01(\x04\x12\x17\n\x0fsequence_number\x18\x03 \x01(\x04\x12\x15\n\rframe_time_us\x18\x04 \x01(\x03\x12\x13\n\x0b\x64\x65\x61\x64line_us\x18\x05 \x01(\x03\x12\x19\n\x11interval_delta_us\x18\x06 \x01(\x03\x12\x18\n\x10on_critical_path\x18\x07 \x01(\x08\x12\x14\n\x0c\x61nimate_only\x18\x08 \x01(\x08\x12\x1d\n\x13source_location_iid\x18\t \x01(\x04H\x00\x12:\n\x0fsource_location\x18\n \x01(\x0b\x32\x1f.perfetto.protos.SourceLocationH\x00\x12#\n\x1b\x66rames_throttled_since_last\x18\x0c \x01(\x03"\xa2\x01\n\x12\x42\x65ginFrameArgsType\x12%\n!BEGIN_FRAME_ARGS_TYPE_UNSPECIFIED\x10\x00\x12!\n\x1d\x42\x45GIN_FRAME_ARGS_TYPE_INVALID\x10\x01\x12 \n\x1c\x42\x45GIN_FRAME_ARGS_TYPE_NORMAL\x10\x02\x12 \n\x1c\x42\x45GIN_FRAME_ARGS_TYPE_MISSED\x10\x03\x42\x0e\n\x0c\x63reated_from"\xc0\x04\n\x12\x42\x65ginImplFrameArgs\x12\x15\n\rupdated_at_us\x18\x01 \x01(\x03\x12\x16\n\x0e\x66inished_at_us\x18\x02 \x01(\x03\x12\x38\n\x05state\x18\x03 \x01(\x0e\x32).perfetto.protos.BeginImplFrameArgs.State\x12\x37\n\x0c\x63urrent_args\x18\x04 \x01(\x0b\x32\x1f.perfetto.protos.BeginFrameArgsH\x00\x12\x34\n\tlast_args\x18\x05 \x01(\x0b\x32\x1f.perfetto.protos.BeginFrameArgsH\x00\x12L\n\x10timestamps_in_us\x18\x06 \x01(\x0b\x32\x32.perfetto.protos.BeginImplFrameArgs.TimestampsInUs\x1a\xc1\x01\n\x0eTimestampsInUs\x12\x16\n\x0einterval_delta\x18\x01 \x01(\x03\x12\x1d\n\x15now_to_deadline_delta\x18\x02 \x01(\x03\x12\x1f\n\x17\x66rame_time_to_now_delta\x18\x03 \x01(\x03\x12$\n\x1c\x66rame_time_to_deadline_delta\x18\x04 \x01(\x03\x12\x0b\n\x03now\x18\x05 \x01(\x03\x12\x12\n\nframe_time\x18\x06 \x01(\x03\x12\x10\n\x08\x64\x65\x61\x64line\x18\x07 \x01(\x03"8\n\x05State\x12\x18\n\x14\x42\x45GIN_FRAME_FINISHED\x10\x00\x12\x15\n\x11\x42\x45GIN_FRAME_USING\x10\x01\x42\x06\n\x04\x61rgs"{\n\x17\x42\x65ginFrameObserverState\x12 \n\x18\x64ropped_begin_frame_args\x18\x01 \x01(\x03\x12>\n\x15last_begin_frame_args\x18\x02 \x01(\x0b\x32\x1f.perfetto.protos.BeginFrameArgs"\x91\x01\n\x15\x42\x65ginFrameSourceState\x12\x11\n\tsource_id\x18\x01 \x01(\r\x12\x0e\n\x06paused\x18\x02 \x01(\x08\x12\x15\n\rnum_observers\x18\x03 \x01(\r\x12>\n\x15last_begin_frame_args\x18\x04 \x01(\x0b\x32\x1f.perfetto.protos.BeginFrameArgs"\xfc\x02\n\x17\x43ompositorTimingHistory\x12\x39\n1begin_main_frame_queue_critical_estimate_delta_us\x18\x01 \x01(\x03\x12=\n5begin_main_frame_queue_not_critical_estimate_delta_us\x18\x02 \x01(\x03\x12\x43\n;begin_main_frame_start_to_ready_to_commit_estimate_delta_us\x18\x03 \x01(\x03\x12\x35\n-commit_to_ready_to_activate_estimate_delta_us\x18\x04 \x01(\x03\x12\'\n\x1fprepare_tiles_estimate_delta_us\x18\x05 \x01(\x03\x12"\n\x1a\x61\x63tivate_estimate_delta_us\x18\x06 \x01(\x03\x12\x1e\n\x16\x64raw_estimate_delta_us\x18\x07 \x01(\x03">\n\x1e\x43hromeContentSettingsEventInfo\x12\x1c\n\x14number_of_exceptions\x18\x01 \x01(\r"\x8f\x08\n\x13\x43hromeFrameReporter\x12\x39\n\x05state\x18\x01 \x01(\x0e\x32*.perfetto.protos.ChromeFrameReporter.State\x12\x44\n\x06reason\x18\x02 \x01(\x0e\x32\x34.perfetto.protos.ChromeFrameReporter.FrameDropReason\x12\x14\n\x0c\x66rame_source\x18\x03 \x01(\x04\x12\x16\n\x0e\x66rame_sequence\x18\x04 \x01(\x04\x12\x1a\n\x12\x61\x66\x66\x65\x63ts_smoothness\x18\x05 \x01(\x08\x12\x46\n\x0cscroll_state\x18\x06 \x01(\x0e\x32\x30.perfetto.protos.ChromeFrameReporter.ScrollState\x12\x1a\n\x12has_main_animation\x18\x07 \x01(\x08\x12 \n\x18has_compositor_animation\x18\x08 \x01(\x08\x12\x1d\n\x15has_smooth_input_main\x18\t \x01(\x08\x12\x1b\n\x13has_missing_content\x18\n \x01(\x08\x12\x1a\n\x12layer_tree_host_id\x18\x0b \x01(\x04\x12\x18\n\x10has_high_latency\x18\x0c \x01(\x08\x12\x42\n\nframe_type\x18\r \x01(\x0e\x32..perfetto.protos.ChromeFrameReporter.FrameType\x12\'\n\x1fhigh_latency_contribution_stage\x18\x0e \x03(\t\x12#\n\x1b\x63heckerboarded_needs_raster\x18\x0f \x01(\x08\x12#\n\x1b\x63heckerboarded_needs_record\x18\x10 \x01(\x08"m\n\x05State\x12\x1b\n\x17STATE_NO_UPDATE_DESIRED\x10\x00\x12\x17\n\x13STATE_PRESENTED_ALL\x10\x01\x12\x1b\n\x17STATE_PRESENTED_PARTIAL\x10\x02\x12\x11\n\rSTATE_DROPPED\x10\x03"~\n\x0f\x46rameDropReason\x12\x16\n\x12REASON_UNSPECIFIED\x10\x00\x12\x1d\n\x19REASON_DISPLAY_COMPOSITOR\x10\x01\x12\x16\n\x12REASON_MAIN_THREAD\x10\x02\x12\x1c\n\x18REASON_CLIENT_COMPOSITOR\x10\x03"h\n\x0bScrollState\x12\x0f\n\x0bSCROLL_NONE\x10\x00\x12\x16\n\x12SCROLL_MAIN_THREAD\x10\x01\x12\x1c\n\x18SCROLL_COMPOSITOR_THREAD\x10\x02\x12\x12\n\x0eSCROLL_UNKNOWN\x10\x03"%\n\tFrameType\x12\n\n\x06\x46ORKED\x10\x00\x12\x0c\n\x08\x42\x41\x43KFILL\x10\x01""\n\x12\x43hromeKeyedService\x12\x0c\n\x04name\x18\x01 \x01(\t"\xfe\r\n\x11\x43hromeLatencyInfo\x12\x10\n\x08trace_id\x18\x01 \x01(\x03\x12\x35\n\x04step\x18\x02 \x01(\x0e\x32\'.perfetto.protos.ChromeLatencyInfo.Step\x12\x1a\n\x12\x66rame_tree_node_id\x18\x03 \x01(\x05\x12H\n\x0e\x63omponent_info\x18\x04 \x03(\x0b\x32\x30.perfetto.protos.ChromeLatencyInfo.ComponentInfo\x12\x14\n\x0cis_coalesced\x18\x05 \x01(\x08\x12\x19\n\x11gesture_scroll_id\x18\x06 \x01(\x03\x12\x10\n\x08touch_id\x18\x07 \x01(\x03\x12@\n\ninput_type\x18\x08 \x01(\x0e\x32,.perfetto.protos.ChromeLatencyInfo.InputType\x1aq\n\rComponentInfo\x12O\n\x0e\x63omponent_type\x18\x01 \x01(\x0e\x32\x37.perfetto.protos.ChromeLatencyInfo.LatencyComponentType\x12\x0f\n\x07time_us\x18\x02 \x01(\x04"\x9a\x03\n\x04Step\x12\x14\n\x10STEP_UNSPECIFIED\x10\x00\x12\x1c\n\x18STEP_SEND_INPUT_EVENT_UI\x10\x03\x12 \n\x1cSTEP_HANDLE_INPUT_EVENT_IMPL\x10\x05\x12(\n$STEP_DID_HANDLE_INPUT_AND_OVERSCROLL\x10\x08\x12 \n\x1cSTEP_HANDLE_INPUT_EVENT_MAIN\x10\x04\x12"\n\x1eSTEP_MAIN_THREAD_SCROLL_UPDATE\x10\x02\x12\'\n#STEP_HANDLE_INPUT_EVENT_MAIN_COMMIT\x10\x01\x12)\n%STEP_HANDLED_INPUT_EVENT_MAIN_OR_IMPL\x10\t\x12!\n\x1dSTEP_HANDLED_INPUT_EVENT_IMPL\x10\n\x12\x15\n\x11STEP_SWAP_BUFFERS\x10\x06\x12\x1a\n\x12STEP_DRAW_AND_SWAP\x10\x07\x1a\x02\x08\x01\x12"\n\x1aSTEP_FINISHED_SWAP_BUFFERS\x10\x0b\x1a\x02\x08\x01"\xf5\x05\n\x14LatencyComponentType\x12\x19\n\x15\x43OMPONENT_UNSPECIFIED\x10\x00\x12+\n\'COMPONENT_INPUT_EVENT_LATENCY_BEGIN_RWH\x10\x01\x12\x38\n4COMPONENT_INPUT_EVENT_LATENCY_SCROLL_UPDATE_ORIGINAL\x10\x02\x12>\n:COMPONENT_INPUT_EVENT_LATENCY_FIRST_SCROLL_UPDATE_ORIGINAL\x10\x03\x12*\n&COMPONENT_INPUT_EVENT_LATENCY_ORIGINAL\x10\x04\x12$\n COMPONENT_INPUT_EVENT_LATENCY_UI\x10\x05\x12/\n+COMPONENT_INPUT_EVENT_LATENCY_RENDERER_MAIN\x10\x06\x12:\n6COMPONENT_INPUT_EVENT_LATENCY_RENDERING_SCHEDULED_MAIN\x10\x07\x12:\n6COMPONENT_INPUT_EVENT_LATENCY_RENDERING_SCHEDULED_IMPL\x10\x08\x12:\n6COMPONENT_INPUT_EVENT_LATENCY_SCROLL_UPDATE_LAST_EVENT\x10\t\x12)\n%COMPONENT_INPUT_EVENT_LATENCY_ACK_RWH\x10\n\x12/\n+COMPONENT_INPUT_EVENT_LATENCY_RENDERER_SWAP\x10\x0b\x12/\n+COMPONENT_DISPLAY_COMPOSITOR_RECEIVED_FRAME\x10\x0c\x12)\n%COMPONENT_INPUT_EVENT_GPU_SWAP_BUFFER\x10\r\x12,\n(COMPONENT_INPUT_EVENT_LATENCY_FRAME_SWAP\x10\x0e"\xac\x01\n\tInputType\x12\x18\n\x14UNSPECIFIED_OR_OTHER\x10\x00\x12\x0f\n\x0bTOUCH_MOVED\x10\x01\x12\x18\n\x14GESTURE_SCROLL_BEGIN\x10\x02\x12\x19\n\x15GESTURE_SCROLL_UPDATE\x10\x03\x12\x16\n\x12GESTURE_SCROLL_END\x10\x04\x12\x0f\n\x0bGESTURE_TAP\x10\x05\x12\x16\n\x12GESTURE_TAP_CANCEL\x10\x06"\xce\x07\n\x0f\x43hromeLegacyIpc\x12\x44\n\rmessage_class\x18\x01 \x01(\x0e\x32-.perfetto.protos.ChromeLegacyIpc.MessageClass\x12\x14\n\x0cmessage_line\x18\x02 \x01(\r"\xde\x06\n\x0cMessageClass\x12\x15\n\x11\x43LASS_UNSPECIFIED\x10\x00\x12\x14\n\x10\x43LASS_AUTOMATION\x10\x01\x12\x0f\n\x0b\x43LASS_FRAME\x10\x02\x12\x0e\n\nCLASS_PAGE\x10\x03\x12\x0e\n\nCLASS_VIEW\x10\x04\x12\x10\n\x0c\x43LASS_WIDGET\x10\x05\x12\x0f\n\x0b\x43LASS_INPUT\x10\x06\x12\x0e\n\nCLASS_TEST\x10\x07\x12\x10\n\x0c\x43LASS_WORKER\x10\x08\x12\x0e\n\nCLASS_NACL\x10\t\x12\x15\n\x11\x43LASS_GPU_CHANNEL\x10\n\x12\x0f\n\x0b\x43LASS_MEDIA\x10\x0b\x12\x0f\n\x0b\x43LASS_PPAPI\x10\x0c\x12\x10\n\x0c\x43LASS_CHROME\x10\r\x12\x0e\n\nCLASS_DRAG\x10\x0e\x12\x0f\n\x0b\x43LASS_PRINT\x10\x0f\x12\x13\n\x0f\x43LASS_EXTENSION\x10\x10\x12\x1b\n\x17\x43LASS_TEXT_INPUT_CLIENT\x10\x11\x12\x14\n\x10\x43LASS_BLINK_TEST\x10\x12\x12\x17\n\x13\x43LASS_ACCESSIBILITY\x10\x13\x12\x13\n\x0f\x43LASS_PRERENDER\x10\x14\x12\x14\n\x10\x43LASS_CHROMOTING\x10\x15\x12\x18\n\x14\x43LASS_BROWSER_PLUGIN\x10\x16\x12\x1a\n\x16\x43LASS_ANDROID_WEB_VIEW\x10\x17\x12\x13\n\x0f\x43LASS_NACL_HOST\x10\x18\x12\x19\n\x15\x43LASS_ENCRYPTED_MEDIA\x10\x19\x12\x0e\n\nCLASS_CAST\x10\x1a\x12\x19\n\x15\x43LASS_GIN_JAVA_BRIDGE\x10\x1b\x12!\n\x1d\x43LASS_CHROME_UTILITY_PRINTING\x10\x1c\x12\x13\n\x0f\x43LASS_OZONE_GPU\x10\x1d\x12\x12\n\x0e\x43LASS_WEB_TEST\x10\x1e\x12\x17\n\x13\x43LASS_NETWORK_HINTS\x10\x1f\x12\x1f\n\x1b\x43LASS_EXTENSIONS_GUEST_VIEW\x10 \x12\x14\n\x10\x43LASS_GUEST_VIEW\x10!\x12\x1f\n\x1b\x43LASS_MEDIA_PLAYER_DELEGATE\x10"\x12\x1a\n\x16\x43LASS_EXTENSION_WORKER\x10#\x12\x1c\n\x18\x43LASS_SUBRESOURCE_FILTER\x10$\x12\x1b\n\x17\x43LASS_UNFREEZABLE_FRAME\x10%"T\n\x11\x43hromeMessagePump\x12\x1e\n\x16sent_messages_in_queue\x18\x01 \x01(\x08\x12\x1f\n\x17io_handler_location_iid\x18\x02 \x01(\x04"\xcc\x01\n\x13\x43hromeMojoEventInfo\x12$\n\x1cwatcher_notify_interface_tag\x18\x01 \x01(\t\x12\x10\n\x08ipc_hash\x18\x02 \x01(\r\x12\x1a\n\x12mojo_interface_tag\x18\x03 \x01(\t\x12!\n\x19mojo_interface_method_iid\x18\x04 \x01(\x04\x12\x10\n\x08is_reply\x18\x05 \x01(\x08\x12\x14\n\x0cpayload_size\x18\x06 \x01(\x04\x12\x16\n\x0e\x64\x61ta_num_bytes\x18\x07 \x01(\x04"~\n\x1c\x43hromeRendererSchedulerState\x12\x32\n\trail_mode\x18\x01 \x01(\x0e\x32\x1f.perfetto.protos.ChromeRAILMode\x12\x17\n\x0fis_backgrounded\x18\x02 \x01(\x08\x12\x11\n\tis_hidden\x18\x03 \x01(\x08"6\n\x0f\x43hromeUserEvent\x12\x0e\n\x06\x61\x63tion\x18\x01 \x01(\t\x12\x13\n\x0b\x61\x63tion_hash\x18\x02 \x01(\x04"P\n\x1b\x43hromeWindowHandleEventInfo\x12\x0b\n\x03\x64pi\x18\x01 \x01(\r\x12\x12\n\nmessage_id\x18\x02 \x01(\r\x12\x10\n\x08hwnd_ptr\x18\x03 \x01(\x06"\x1f\n\nScreenshot\x12\x11\n\tjpg_image\x18\x01 \x01(\x0c"(\n\rTaskExecution\x12\x17\n\x0fposted_from_iid\x18\x01 \x01(\x04"\xe9\x17\n\nTrackEvent\x12\x15\n\rcategory_iids\x18\x03 \x03(\x04\x12\x12\n\ncategories\x18\x16 \x03(\t\x12\x12\n\x08name_iid\x18\n \x01(\x04H\x00\x12\x0e\n\x04name\x18\x17 \x01(\tH\x00\x12.\n\x04type\x18\t \x01(\x0e\x32 .perfetto.protos.TrackEvent.Type\x12\x12\n\ntrack_uuid\x18\x0b \x01(\x04\x12\x17\n\rcounter_value\x18\x1e \x01(\x03H\x01\x12\x1e\n\x14\x64ouble_counter_value\x18, \x01(\x01H\x01\x12!\n\x19\x65xtra_counter_track_uuids\x18\x1f \x03(\x04\x12\x1c\n\x14\x65xtra_counter_values\x18\x0c \x03(\x03\x12(\n extra_double_counter_track_uuids\x18- \x03(\x04\x12#\n\x1b\x65xtra_double_counter_values\x18. \x03(\x01\x12\x18\n\x0c\x66low_ids_old\x18$ \x03(\x04\x42\x02\x18\x01\x12\x10\n\x08\x66low_ids\x18/ \x03(\x06\x12$\n\x18terminating_flow_ids_old\x18* \x03(\x04\x42\x02\x18\x01\x12\x1c\n\x14terminating_flow_ids\x18\x30 \x03(\x06\x12;\n\x11\x64\x65\x62ug_annotations\x18\x04 \x03(\x0b\x32 .perfetto.protos.DebugAnnotation\x12\x36\n\x0etask_execution\x18\x05 \x01(\x0b\x32\x1e.perfetto.protos.TaskExecution\x12\x30\n\x0blog_message\x18\x15 \x01(\x0b\x32\x1b.perfetto.protos.LogMessage\x12K\n\x12\x63\x63_scheduler_state\x18\x18 \x01(\x0b\x32/.perfetto.protos.ChromeCompositorSchedulerState\x12;\n\x11\x63hrome_user_event\x18\x19 \x01(\x0b\x32 .perfetto.protos.ChromeUserEvent\x12\x41\n\x14\x63hrome_keyed_service\x18\x1a \x01(\x0b\x32#.perfetto.protos.ChromeKeyedService\x12;\n\x11\x63hrome_legacy_ipc\x18\x1b \x01(\x0b\x32 .perfetto.protos.ChromeLegacyIpc\x12G\n\x17\x63hrome_histogram_sample\x18\x1c \x01(\x0b\x32&.perfetto.protos.ChromeHistogramSample\x12?\n\x13\x63hrome_latency_info\x18\x1d \x01(\x0b\x32".perfetto.protos.ChromeLatencyInfo\x12\x43\n\x15\x63hrome_frame_reporter\x18 \x01(\x0b\x32$.perfetto.protos.ChromeFrameReporter\x12R\n\x1d\x63hrome_application_state_info\x18\' \x01(\x0b\x32+.perfetto.protos.ChromeApplicationStateInfo\x12V\n\x1f\x63hrome_renderer_scheduler_state\x18( \x01(\x0b\x32-.perfetto.protos.ChromeRendererSchedulerState\x12U\n\x1f\x63hrome_window_handle_event_info\x18) \x01(\x0b\x32,.perfetto.protos.ChromeWindowHandleEventInfo\x12[\n"chrome_content_settings_event_info\x18+ \x01(\x0b\x32/.perfetto.protos.ChromeContentSettingsEventInfo\x12G\n\x17\x63hrome_active_processes\x18\x31 \x01(\x0b\x32&.perfetto.protos.ChromeActiveProcesses\x12/\n\nscreenshot\x18\x32 \x01(\x0b\x32\x1b.perfetto.protos.Screenshot\x12:\n\x0fsource_location\x18! \x01(\x0b\x32\x1f.perfetto.protos.SourceLocationH\x02\x12\x1d\n\x13source_location_iid\x18" \x01(\x04H\x02\x12?\n\x13\x63hrome_message_pump\x18# \x01(\x0b\x32".perfetto.protos.ChromeMessagePump\x12\x44\n\x16\x63hrome_mojo_event_info\x18& \x01(\x0b\x32$.perfetto.protos.ChromeMojoEventInfo\x12\x1c\n\x12timestamp_delta_us\x18\x01 \x01(\x03H\x03\x12\x1f\n\x15timestamp_absolute_us\x18\x10 \x01(\x03H\x03\x12\x1e\n\x14thread_time_delta_us\x18\x02 \x01(\x03H\x04\x12!\n\x17thread_time_absolute_us\x18\x11 \x01(\x03H\x04\x12(\n\x1ethread_instruction_count_delta\x18\x08 \x01(\x03H\x05\x12+\n!thread_instruction_count_absolute\x18\x14 \x01(\x03H\x05\x12=\n\x0clegacy_event\x18\x06 \x01(\x0b\x32\'.perfetto.protos.TrackEvent.LegacyEvent\x1a\xaa\x05\n\x0bLegacyEvent\x12\x10\n\x08name_iid\x18\x01 \x01(\x04\x12\r\n\x05phase\x18\x02 \x01(\x05\x12\x13\n\x0b\x64uration_us\x18\x03 \x01(\x03\x12\x1a\n\x12thread_duration_us\x18\x04 \x01(\x03\x12 \n\x18thread_instruction_delta\x18\x0f \x01(\x03\x12\x15\n\x0bunscoped_id\x18\x06 \x01(\x04H\x00\x12\x12\n\x08local_id\x18\n \x01(\x04H\x00\x12\x13\n\tglobal_id\x18\x0b \x01(\x04H\x00\x12\x10\n\x08id_scope\x18\x07 \x01(\t\x12\x15\n\ruse_async_tts\x18\t \x01(\x08\x12\x0f\n\x07\x62ind_id\x18\x08 \x01(\x04\x12\x19\n\x11\x62ind_to_enclosing\x18\x0c \x01(\x08\x12M\n\x0e\x66low_direction\x18\r \x01(\x0e\x32\x35.perfetto.protos.TrackEvent.LegacyEvent.FlowDirection\x12V\n\x13instant_event_scope\x18\x0e \x01(\x0e\x32\x39.perfetto.protos.TrackEvent.LegacyEvent.InstantEventScope\x12\x14\n\x0cpid_override\x18\x12 \x01(\x05\x12\x14\n\x0ctid_override\x18\x13 \x01(\x05"P\n\rFlowDirection\x12\x14\n\x10\x46LOW_UNSPECIFIED\x10\x00\x12\x0b\n\x07\x46LOW_IN\x10\x01\x12\x0c\n\x08\x46LOW_OUT\x10\x02\x12\x0e\n\nFLOW_INOUT\x10\x03"a\n\x11InstantEventScope\x12\x15\n\x11SCOPE_UNSPECIFIED\x10\x00\x12\x10\n\x0cSCOPE_GLOBAL\x10\x01\x12\x11\n\rSCOPE_PROCESS\x10\x02\x12\x10\n\x0cSCOPE_THREAD\x10\x03\x42\x04\n\x02idJ\x04\x08\x05\x10\x06"j\n\x04Type\x12\x14\n\x10TYPE_UNSPECIFIED\x10\x00\x12\x14\n\x10TYPE_SLICE_BEGIN\x10\x01\x12\x12\n\x0eTYPE_SLICE_END\x10\x02\x12\x10\n\x0cTYPE_INSTANT\x10\x03\x12\x10\n\x0cTYPE_COUNTER\x10\x04*\x06\x08\xe8\x07\x10\xd0\x0f*\x06\x08\xd0\x0f\x10\xd1\x0f*\x06\x08\xd1\x0f\x10\xb8\x17*\x06\x08\xb8\x17\x10\xacM*\x06\x08\xacM\x10\x91NB\x0c\n\nname_fieldB\x15\n\x13\x63ounter_value_fieldB\x17\n\x15source_location_fieldB\x0b\n\ttimestampB\r\n\x0bthread_timeB\x1a\n\x18thread_instruction_countJ\x04\x08\x33\x10\x34"u\n\x12TrackEventDefaults\x12\x12\n\ntrack_uuid\x18\x0b \x01(\x04\x12!\n\x19\x65xtra_counter_track_uuids\x18\x1f \x03(\x04\x12(\n extra_double_counter_track_uuids\x18- \x03(\x04"*\n\rEventCategory\x12\x0b\n\x03iid\x18\x01 \x01(\x04\x12\x0c\n\x04name\x18\x02 \x01(\t"&\n\tEventName\x12\x0b\n\x03iid\x18\x01 \x01(\x04\x12\x0c\n\x04name\x18\x02 \x01(\t"\x8a\x10\n\x0cInternedData\x12\x38\n\x10\x65vent_categories\x18\x01 \x03(\x0b\x32\x1e.perfetto.protos.EventCategory\x12/\n\x0b\x65vent_names\x18\x02 \x03(\x0b\x32\x1a.perfetto.protos.EventName\x12\x44\n\x16\x64\x65\x62ug_annotation_names\x18\x03 \x03(\x0b\x32$.perfetto.protos.DebugAnnotationName\x12X\n!debug_annotation_value_type_names\x18\x1b \x03(\x0b\x32-.perfetto.protos.DebugAnnotationValueTypeName\x12\x39\n\x10source_locations\x18\x04 \x03(\x0b\x32\x1f.perfetto.protos.SourceLocation\x12R\n\x1dunsymbolized_source_locations\x18\x1c \x03(\x0b\x32+.perfetto.protos.UnsymbolizedSourceLocation\x12\x39\n\x10log_message_body\x18\x14 \x03(\x0b\x32\x1f.perfetto.protos.LogMessageBody\x12\x37\n\x0fhistogram_names\x18\x19 \x03(\x0b\x32\x1e.perfetto.protos.HistogramName\x12\x32\n\tbuild_ids\x18\x10 \x03(\x0b\x32\x1f.perfetto.protos.InternedString\x12\x36\n\rmapping_paths\x18\x11 \x03(\x0b\x32\x1f.perfetto.protos.InternedString\x12\x35\n\x0csource_paths\x18\x12 \x03(\x0b\x32\x1f.perfetto.protos.InternedString\x12\x37\n\x0e\x66unction_names\x18\x05 \x03(\x0b\x32\x1f.perfetto.protos.InternedString\x12\x45\n\x16profiled_frame_symbols\x18\x15 \x03(\x0b\x32%.perfetto.protos.ProfiledFrameSymbols\x12*\n\x08mappings\x18\x13 \x03(\x0b\x32\x18.perfetto.protos.Mapping\x12&\n\x06\x66rames\x18\x06 \x03(\x0b\x32\x16.perfetto.protos.Frame\x12.\n\ncallstacks\x18\x07 \x03(\x0b\x32\x1a.perfetto.protos.Callstack\x12;\n\x12vulkan_memory_keys\x18\x16 \x03(\x0b\x32\x1f.perfetto.protos.InternedString\x12\x43\n\x11graphics_contexts\x18\x17 \x03(\x0b\x32(.perfetto.protos.InternedGraphicsContext\x12P\n\x12gpu_specifications\x18\x18 \x03(\x0b\x32\x34.perfetto.protos.InternedGpuRenderStageSpecification\x12\x37\n\x0ekernel_symbols\x18\x1a \x03(\x0b\x32\x1f.perfetto.protos.InternedString\x12G\n\x1e\x64\x65\x62ug_annotation_string_values\x18\x1d \x03(\x0b\x32\x1f.perfetto.protos.InternedString\x12=\n\x0epacket_context\x18\x1e \x03(\x0b\x32%.perfetto.protos.NetworkPacketContext\x12>\n\x13v8_js_function_name\x18\x1f \x03(\x0b\x32!.perfetto.protos.InternedV8String\x12=\n\x0ev8_js_function\x18 \x03(\x0b\x32%.perfetto.protos.InternedV8JsFunction\x12\x39\n\x0cv8_js_script\x18! \x03(\x0b\x32#.perfetto.protos.InternedV8JsScript\x12=\n\x0ev8_wasm_script\x18" \x03(\x0b\x32%.perfetto.protos.InternedV8WasmScript\x12\x36\n\nv8_isolate\x18# \x03(\x0b\x32".perfetto.protos.InternedV8Isolate\x12=\n\x14protolog_string_args\x18$ \x03(\x0b\x32\x1f.perfetto.protos.InternedString\x12<\n\x13protolog_stacktrace\x18% \x03(\x0b\x32\x1f.perfetto.protos.InternedString\x12\x41\n\x18viewcapture_package_name\x18& \x03(\x0b\x32\x1f.perfetto.protos.InternedString\x12@\n\x17viewcapture_window_name\x18\' \x03(\x0b\x32\x1f.perfetto.protos.InternedString\x12<\n\x13viewcapture_view_id\x18( \x03(\x0b\x32\x1f.perfetto.protos.InternedString\x12?\n\x16viewcapture_class_name\x18) \x03(\x0b\x32\x1f.perfetto.protos.InternedString"\xf0\x07\n\x15MemoryTrackerSnapshot\x12\x16\n\x0eglobal_dump_id\x18\x01 \x01(\x04\x12M\n\x0flevel_of_detail\x18\x02 \x01(\x0e\x32\x34.perfetto.protos.MemoryTrackerSnapshot.LevelOfDetail\x12T\n\x14process_memory_dumps\x18\x03 \x03(\x0b\x32\x36.perfetto.protos.MemoryTrackerSnapshot.ProcessSnapshot\x1a\xce\x05\n\x0fProcessSnapshot\x12\x0b\n\x03pid\x18\x01 \x01(\x05\x12Z\n\x0f\x61llocator_dumps\x18\x02 \x03(\x0b\x32\x41.perfetto.protos.MemoryTrackerSnapshot.ProcessSnapshot.MemoryNode\x12W\n\x0cmemory_edges\x18\x03 \x03(\x0b\x32\x41.perfetto.protos.MemoryTrackerSnapshot.ProcessSnapshot.MemoryEdge\x1a\x9b\x03\n\nMemoryNode\x12\n\n\x02id\x18\x01 \x01(\x04\x12\x15\n\rabsolute_name\x18\x02 \x01(\t\x12\x0c\n\x04weak\x18\x03 \x01(\x08\x12\x12\n\nsize_bytes\x18\x04 \x01(\x04\x12\x62\n\x07\x65ntries\x18\x05 \x03(\x0b\x32Q.perfetto.protos.MemoryTrackerSnapshot.ProcessSnapshot.MemoryNode.MemoryNodeEntry\x1a\xe3\x01\n\x0fMemoryNodeEntry\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x66\n\x05units\x18\x02 \x01(\x0e\x32W.perfetto.protos.MemoryTrackerSnapshot.ProcessSnapshot.MemoryNode.MemoryNodeEntry.Units\x12\x14\n\x0cvalue_uint64\x18\x03 \x01(\x04\x12\x14\n\x0cvalue_string\x18\x04 \x01(\t".\n\x05Units\x12\x0f\n\x0bUNSPECIFIED\x10\x00\x12\t\n\x05\x42YTES\x10\x01\x12\t\n\x05\x43OUNT\x10\x02\x1a[\n\nMemoryEdge\x12\x11\n\tsource_id\x18\x01 \x01(\x04\x12\x11\n\ttarget_id\x18\x02 \x01(\x04\x12\x12\n\nimportance\x18\x03 \x01(\r\x12\x13\n\x0boverridable\x18\x04 \x01(\x08"I\n\rLevelOfDetail\x12\x0f\n\x0b\x44\x45TAIL_FULL\x10\x00\x12\x10\n\x0c\x44\x45TAIL_LIGHT\x10\x01\x12\x15\n\x11\x44\x45TAIL_BACKGROUND\x10\x02"\xa1\x04\n\x11PerfettoMetatrace\x12\x12\n\x08\x65vent_id\x18\x01 \x01(\rH\x00\x12\x14\n\ncounter_id\x18\x02 \x01(\rH\x00\x12\x14\n\nevent_name\x18\x08 \x01(\tH\x00\x12\x18\n\x0e\x65vent_name_iid\x18\x0b \x01(\x04H\x00\x12\x16\n\x0c\x63ounter_name\x18\t \x01(\tH\x00\x12\x19\n\x11\x65vent_duration_ns\x18\x03 \x01(\x04\x12\x15\n\rcounter_value\x18\x04 \x01(\x05\x12\x11\n\tthread_id\x18\x05 \x01(\r\x12\x14\n\x0chas_overruns\x18\x06 \x01(\x08\x12\x34\n\x04\x61rgs\x18\x07 \x03(\x0b\x32&.perfetto.protos.PerfettoMetatrace.Arg\x12K\n\x10interned_strings\x18\n \x03(\x0b\x32\x31.perfetto.protos.PerfettoMetatrace.InternedString\x1a\x7f\n\x03\x41rg\x12\r\n\x03key\x18\x01 \x01(\tH\x00\x12\x11\n\x07key_iid\x18\x03 \x01(\x04H\x00\x12\x0f\n\x05value\x18\x02 \x01(\tH\x01\x12\x13\n\tvalue_iid\x18\x04 \x01(\x04H\x01\x42\x15\n\x13key_or_interned_keyB\x19\n\x17value_or_interned_value\x1a,\n\x0eInternedString\x12\x0b\n\x03iid\x18\x01 \x01(\x04\x12\r\n\x05value\x18\x02 \x01(\tB\r\n\x0brecord_type"\xec\x01\n\x13TracingServiceEvent\x12\x19\n\x0ftracing_started\x18\x02 \x01(\x08H\x00\x12"\n\x18\x61ll_data_sources_started\x18\x01 \x01(\x08H\x00\x12"\n\x18\x61ll_data_sources_flushed\x18\x03 \x01(\x08H\x00\x12(\n\x1eread_tracing_buffers_completed\x18\x04 \x01(\x08H\x00\x12\x1a\n\x10tracing_disabled\x18\x05 \x01(\x08H\x00\x12\x1e\n\x14seized_for_bugreport\x18\x06 \x01(\x08H\x00\x42\x0c\n\nevent_type"`\n\x15\x41ndroidEnergyConsumer\x12\x1a\n\x12\x65nergy_consumer_id\x18\x01 \x01(\x05\x12\x0f\n\x07ordinal\x18\x02 \x01(\x05\x12\x0c\n\x04type\x18\x03 \x01(\t\x12\x0c\n\x04name\x18\x04 \x01(\t"c\n\x1f\x41ndroidEnergyConsumerDescriptor\x12@\n\x10\x65nergy_consumers\x18\x01 \x03(\x0b\x32&.perfetto.protos.AndroidEnergyConsumer"\xc0\x02\n AndroidEnergyEstimationBreakdown\x12T\n\x1a\x65nergy_consumer_descriptor\x18\x01 \x01(\x0b\x32\x30.perfetto.protos.AndroidEnergyConsumerDescriptor\x12\x1a\n\x12\x65nergy_consumer_id\x18\x02 \x01(\x05\x12\x12\n\nenergy_uws\x18\x03 \x01(\x03\x12_\n\x11per_uid_breakdown\x18\x04 \x03(\x0b\x32\x44.perfetto.protos.AndroidEnergyEstimationBreakdown.EnergyUidBreakdown\x1a\x35\n\x12\x45nergyUidBreakdown\x12\x0b\n\x03uid\x18\x01 \x01(\x05\x12\x12\n\nenergy_uws\x18\x02 \x01(\x03"\xbb\x03\n\x14\x45ntityStateResidency\x12R\n\x12power_entity_state\x18\x01 \x03(\x0b\x32\x36.perfetto.protos.EntityStateResidency.PowerEntityState\x12G\n\tresidency\x18\x02 \x03(\x0b\x32\x34.perfetto.protos.EntityStateResidency.StateResidency\x1a\x66\n\x10PowerEntityState\x12\x14\n\x0c\x65ntity_index\x18\x01 \x01(\x05\x12\x13\n\x0bstate_index\x18\x02 \x01(\x05\x12\x13\n\x0b\x65ntity_name\x18\x03 \x01(\t\x12\x12\n\nstate_name\x18\x04 \x01(\t\x1a\x9d\x01\n\x0eStateResidency\x12\x14\n\x0c\x65ntity_index\x18\x01 \x01(\x05\x12\x13\n\x0bstate_index\x18\x02 \x01(\x05\x12\x1e\n\x16total_time_in_state_ms\x18\x03 \x01(\x04\x12\x1f\n\x17total_state_entry_count\x18\x04 \x01(\x04\x12\x1f\n\x17last_entry_timestamp_ms\x18\x05 \x01(\x04"\xb1\x01\n\x0f\x42\x61tteryCounters\x12\x1a\n\x12\x63harge_counter_uah\x18\x01 \x01(\x03\x12\x18\n\x10\x63\x61pacity_percent\x18\x02 \x01(\x02\x12\x12\n\ncurrent_ua\x18\x03 \x01(\x03\x12\x16\n\x0e\x63urrent_avg_ua\x18\x04 \x01(\x03\x12\x0c\n\x04name\x18\x05 \x01(\t\x12\x1a\n\x12\x65nergy_counter_uwh\x18\x06 \x01(\x03\x12\x12\n\nvoltage_uv\x18\x07 \x01(\x03"\xb1\x02\n\nPowerRails\x12\x43\n\x0frail_descriptor\x18\x01 \x03(\x0b\x32*.perfetto.protos.PowerRails.RailDescriptor\x12;\n\x0b\x65nergy_data\x18\x02 \x03(\x0b\x32&.perfetto.protos.PowerRails.EnergyData\x1a^\n\x0eRailDescriptor\x12\r\n\x05index\x18\x01 \x01(\r\x12\x11\n\trail_name\x18\x02 \x01(\t\x12\x13\n\x0bsubsys_name\x18\x03 \x01(\t\x12\x15\n\rsampling_rate\x18\x04 \x01(\r\x1a\x41\n\nEnergyData\x12\r\n\x05index\x18\x01 \x01(\r\x12\x14\n\x0ctimestamp_ms\x18\x02 \x01(\x04\x12\x0e\n\x06\x65nergy\x18\x03 \x01(\x04"F\n\x10ObfuscatedMember\x12\x17\n\x0fobfuscated_name\x18\x01 \x01(\t\x12\x19\n\x11\x64\x65obfuscated_name\x18\x02 \x01(\t"\xc3\x01\n\x0fObfuscatedClass\x12\x17\n\x0fobfuscated_name\x18\x01 \x01(\t\x12\x19\n\x11\x64\x65obfuscated_name\x18\x02 \x01(\t\x12=\n\x12obfuscated_members\x18\x03 \x03(\x0b\x32!.perfetto.protos.ObfuscatedMember\x12=\n\x12obfuscated_methods\x18\x04 \x03(\x0b\x32!.perfetto.protos.ObfuscatedMember"\x80\x01\n\x14\x44\x65obfuscationMapping\x12\x14\n\x0cpackage_name\x18\x01 \x01(\t\x12\x14\n\x0cversion_code\x18\x02 \x01(\x03\x12<\n\x12obfuscated_classes\x18\x03 \x03(\x0b\x32 .perfetto.protos.ObfuscatedClass"\xb6\x03\n\rHeapGraphRoot\x12\x16\n\nobject_ids\x18\x01 \x03(\x04\x42\x02\x10\x01\x12\x36\n\troot_type\x18\x02 \x01(\x0e\x32#.perfetto.protos.HeapGraphRoot.Type"\xd4\x02\n\x04Type\x12\x10\n\x0cROOT_UNKNOWN\x10\x00\x12\x13\n\x0fROOT_JNI_GLOBAL\x10\x01\x12\x12\n\x0eROOT_JNI_LOCAL\x10\x02\x12\x13\n\x0fROOT_JAVA_FRAME\x10\x03\x12\x15\n\x11ROOT_NATIVE_STACK\x10\x04\x12\x15\n\x11ROOT_STICKY_CLASS\x10\x05\x12\x15\n\x11ROOT_THREAD_BLOCK\x10\x06\x12\x15\n\x11ROOT_MONITOR_USED\x10\x07\x12\x16\n\x12ROOT_THREAD_OBJECT\x10\x08\x12\x18\n\x14ROOT_INTERNED_STRING\x10\t\x12\x13\n\x0fROOT_FINALIZING\x10\n\x12\x11\n\rROOT_DEBUGGER\x10\x0b\x12\x1a\n\x16ROOT_REFERENCE_CLEANUP\x10\x0c\x12\x14\n\x10ROOT_VM_INTERNAL\x10\r\x12\x14\n\x10ROOT_JNI_MONITOR\x10\x0e"\xe4\x03\n\rHeapGraphType\x12\n\n\x02id\x18\x01 \x01(\x04\x12\x13\n\x0blocation_id\x18\x02 \x01(\x04\x12\x12\n\nclass_name\x18\x03 \x01(\t\x12\x13\n\x0bobject_size\x18\x04 \x01(\x04\x12\x15\n\rsuperclass_id\x18\x05 \x01(\x04\x12\x1e\n\x12reference_field_id\x18\x06 \x03(\x04\x42\x02\x10\x01\x12\x31\n\x04kind\x18\x07 \x01(\x0e\x32#.perfetto.protos.HeapGraphType.Kind\x12\x16\n\x0e\x63lassloader_id\x18\x08 \x01(\x04"\x86\x02\n\x04Kind\x12\x10\n\x0cKIND_UNKNOWN\x10\x00\x12\x0f\n\x0bKIND_NORMAL\x10\x01\x12\x15\n\x11KIND_NOREFERENCES\x10\x02\x12\x0f\n\x0bKIND_STRING\x10\x03\x12\x0e\n\nKIND_ARRAY\x10\x04\x12\x0e\n\nKIND_CLASS\x10\x05\x12\x14\n\x10KIND_CLASSLOADER\x10\x06\x12\x11\n\rKIND_DEXCACHE\x10\x07\x12\x17\n\x13KIND_SOFT_REFERENCE\x10\x08\x12\x17\n\x13KIND_WEAK_REFERENCE\x10\t\x12\x1c\n\x18KIND_FINALIZER_REFERENCE\x10\n\x12\x1a\n\x16KIND_PHANTOM_REFERENCE\x10\x0b"\xf6\x01\n\x0fHeapGraphObject\x12\x0c\n\x02id\x18\x01 \x01(\x04H\x00\x12\x12\n\x08id_delta\x18\x07 \x01(\x04H\x00\x12\x0f\n\x07type_id\x18\x02 \x01(\x04\x12\x11\n\tself_size\x18\x03 \x01(\x04\x12\x1f\n\x17reference_field_id_base\x18\x06 \x01(\x04\x12\x1e\n\x12reference_field_id\x18\x04 \x03(\x04\x42\x02\x10\x01\x12\x1f\n\x13reference_object_id\x18\x05 \x03(\x04\x42\x02\x10\x01\x12-\n%native_allocation_registry_size_field\x18\x08 \x01(\x03\x42\x0c\n\nidentifier"\xc0\x02\n\tHeapGraph\x12\x0b\n\x03pid\x18\x01 \x01(\x05\x12\x31\n\x07objects\x18\x02 \x03(\x0b\x32 .perfetto.protos.HeapGraphObject\x12-\n\x05roots\x18\x07 \x03(\x0b\x32\x1e.perfetto.protos.HeapGraphRoot\x12-\n\x05types\x18\t \x03(\x0b\x32\x1e.perfetto.protos.HeapGraphType\x12\x34\n\x0b\x66ield_names\x18\x04 \x03(\x0b\x32\x1f.perfetto.protos.InternedString\x12\x37\n\x0elocation_names\x18\x08 \x03(\x0b\x32\x1f.perfetto.protos.InternedString\x12\x11\n\tcontinued\x18\x05 \x01(\x08\x12\r\n\x05index\x18\x06 \x01(\x04J\x04\x08\x03\x10\x04"\xbc\x0b\n\rProfilePacket\x12\x30\n\x07strings\x18\x01 \x03(\x0b\x32\x1f.perfetto.protos.InternedString\x12*\n\x08mappings\x18\x04 \x03(\x0b\x32\x18.perfetto.protos.Mapping\x12&\n\x06\x66rames\x18\x02 \x03(\x0b\x32\x16.perfetto.protos.Frame\x12.\n\ncallstacks\x18\x03 \x03(\x0b\x32\x1a.perfetto.protos.Callstack\x12H\n\rprocess_dumps\x18\x05 \x03(\x0b\x32\x31.perfetto.protos.ProfilePacket.ProcessHeapSamples\x12\x11\n\tcontinued\x18\x06 \x01(\x08\x12\r\n\x05index\x18\x07 \x01(\x04\x1a\xba\x01\n\nHeapSample\x12\x14\n\x0c\x63\x61llstack_id\x18\x01 \x01(\x04\x12\x16\n\x0eself_allocated\x18\x02 \x01(\x04\x12\x12\n\nself_freed\x18\x03 \x01(\x04\x12\x10\n\x08self_max\x18\x08 \x01(\x04\x12\x16\n\x0eself_max_count\x18\t \x01(\x04\x12\x11\n\ttimestamp\x18\x04 \x01(\x04\x12\x13\n\x0b\x61lloc_count\x18\x05 \x01(\x04\x12\x12\n\nfree_count\x18\x06 \x01(\x04J\x04\x08\x07\x10\x08\x1a\x8f\x01\n\tHistogram\x12@\n\x07\x62uckets\x18\x01 \x03(\x0b\x32/.perfetto.protos.ProfilePacket.Histogram.Bucket\x1a@\n\x06\x42ucket\x12\x13\n\x0bupper_limit\x18\x01 \x01(\x04\x12\x12\n\nmax_bucket\x18\x02 \x01(\x08\x12\r\n\x05\x63ount\x18\x03 \x01(\x04\x1a\xde\x01\n\x0cProcessStats\x12\x18\n\x10unwinding_errors\x18\x01 \x01(\x04\x12\x14\n\x0cheap_samples\x18\x02 \x01(\x04\x12\x14\n\x0cmap_reparses\x18\x03 \x01(\x04\x12\x43\n\x11unwinding_time_us\x18\x04 \x01(\x0b\x32(.perfetto.protos.ProfilePacket.Histogram\x12\x1f\n\x17total_unwinding_time_us\x18\x05 \x01(\x04\x12"\n\x1a\x63lient_spinlock_blocked_us\x18\x06 \x01(\x04\x1a\xd8\x04\n\x12ProcessHeapSamples\x12\x0b\n\x03pid\x18\x01 \x01(\x04\x12\x14\n\x0c\x66rom_startup\x18\x03 \x01(\x08\x12\x1b\n\x13rejected_concurrent\x18\x04 \x01(\x08\x12\x14\n\x0c\x64isconnected\x18\x06 \x01(\x08\x12\x16\n\x0e\x62uffer_overran\x18\x07 \x01(\x08\x12S\n\x0c\x63lient_error\x18\x0e \x01(\x0e\x32=.perfetto.protos.ProfilePacket.ProcessHeapSamples.ClientError\x12\x18\n\x10\x62uffer_corrupted\x18\x08 \x01(\x08\x12\x15\n\rhit_guardrail\x18\n \x01(\x08\x12\x11\n\theap_name\x18\x0b \x01(\t\x12\x1f\n\x17sampling_interval_bytes\x18\x0c \x01(\x04\x12$\n\x1corig_sampling_interval_bytes\x18\r \x01(\x04\x12\x11\n\ttimestamp\x18\t \x01(\x04\x12:\n\x05stats\x18\x05 \x01(\x0b\x32+.perfetto.protos.ProfilePacket.ProcessStats\x12:\n\x07samples\x18\x02 \x03(\x0b\x32).perfetto.protos.ProfilePacket.HeapSample"i\n\x0b\x43lientError\x12\x15\n\x11\x43LIENT_ERROR_NONE\x10\x00\x12\x1c\n\x18\x43LIENT_ERROR_HIT_TIMEOUT\x10\x01\x12%\n!CLIENT_ERROR_INVALID_STACK_BOUNDS\x10\x02"\x9d\x01\n\x13StreamingAllocation\x12\x0f\n\x07\x61\x64\x64ress\x18\x01 \x03(\x04\x12\x0c\n\x04size\x18\x02 \x03(\x04\x12\x13\n\x0bsample_size\x18\x03 \x03(\x04\x12(\n clock_monotonic_coarse_timestamp\x18\x04 \x03(\x04\x12\x0f\n\x07heap_id\x18\x05 \x03(\r\x12\x17\n\x0fsequence_number\x18\x06 \x03(\x04"J\n\rStreamingFree\x12\x0f\n\x07\x61\x64\x64ress\x18\x01 \x03(\x04\x12\x0f\n\x07heap_id\x18\x02 \x03(\r\x12\x17\n\x0fsequence_number\x18\x03 \x03(\x04"e\n\x16StreamingProfilePacket\x12\x15\n\rcallstack_iid\x18\x01 \x03(\x04\x12\x1a\n\x12timestamp_delta_us\x18\x02 \x03(\x03\x12\x18\n\x10process_priority\x18\x03 \x01(\x05"\x90\x05\n\tProfiling"|\n\x07\x43puMode\x12\x10\n\x0cMODE_UNKNOWN\x10\x00\x12\x0f\n\x0bMODE_KERNEL\x10\x01\x12\r\n\tMODE_USER\x10\x02\x12\x13\n\x0fMODE_HYPERVISOR\x10\x03\x12\x15\n\x11MODE_GUEST_KERNEL\x10\x04\x12\x13\n\x0fMODE_GUEST_USER\x10\x05"\x84\x04\n\x10StackUnwindError\x12\x18\n\x14UNWIND_ERROR_UNKNOWN\x10\x00\x12\x15\n\x11UNWIND_ERROR_NONE\x10\x01\x12\x1f\n\x1bUNWIND_ERROR_MEMORY_INVALID\x10\x02\x12\x1c\n\x18UNWIND_ERROR_UNWIND_INFO\x10\x03\x12\x1c\n\x18UNWIND_ERROR_UNSUPPORTED\x10\x04\x12\x1c\n\x18UNWIND_ERROR_INVALID_MAP\x10\x05\x12$\n UNWIND_ERROR_MAX_FRAMES_EXCEEDED\x10\x06\x12\x1f\n\x1bUNWIND_ERROR_REPEATED_FRAME\x10\x07\x12\x1c\n\x18UNWIND_ERROR_INVALID_ELF\x10\x08\x12\x1c\n\x18UNWIND_ERROR_SYSTEM_CALL\x10\t\x12\x1f\n\x1bUNWIND_ERROR_THREAD_TIMEOUT\x10\n\x12&\n"UNWIND_ERROR_THREAD_DOES_NOT_EXIST\x10\x0b\x12\x19\n\x15UNWIND_ERROR_BAD_ARCH\x10\x0c\x12\x1b\n\x17UNWIND_ERROR_MAPS_PARSE\x10\r\x12"\n\x1eUNWIND_ERROR_INVALID_PARAMETER\x10\x0e\x12\x1c\n\x18UNWIND_ERROR_PTRACE_CALL\x10\x0f"\xb6\x06\n\nPerfSample\x12\x0b\n\x03\x63pu\x18\x01 \x01(\r\x12\x0b\n\x03pid\x18\x02 \x01(\r\x12\x0b\n\x03tid\x18\x03 \x01(\r\x12\x34\n\x08\x63pu_mode\x18\x05 \x01(\x0e\x32".perfetto.protos.Profiling.CpuMode\x12\x16\n\x0etimebase_count\x18\x06 \x01(\x04\x12\x15\n\rcallstack_iid\x18\x04 \x01(\x04\x12\x43\n\x0cunwind_error\x18\x10 \x01(\x0e\x32+.perfetto.protos.Profiling.StackUnwindErrorH\x00\x12\x1b\n\x13kernel_records_lost\x18\x11 \x01(\x04\x12M\n\x15sample_skipped_reason\x18\x12 \x01(\x0e\x32,.perfetto.protos.PerfSample.SampleSkipReasonH\x01\x12\x41\n\x0eproducer_event\x18\x13 \x01(\x0b\x32).perfetto.protos.PerfSample.ProducerEvent\x1a\xdc\x01\n\rProducerEvent\x12\\\n\x12source_stop_reason\x18\x01 \x01(\x0e\x32>.perfetto.protos.PerfSample.ProducerEvent.DataSourceStopReasonH\x00"N\n\x14\x44\x61taSourceStopReason\x12\x19\n\x15PROFILER_STOP_UNKNOWN\x10\x00\x12\x1b\n\x17PROFILER_STOP_GUARDRAIL\x10\x01\x42\x1d\n\x1boptional_source_stop_reason"\x8d\x01\n\x10SampleSkipReason\x12\x19\n\x15PROFILER_SKIP_UNKNOWN\x10\x00\x12\x1c\n\x18PROFILER_SKIP_READ_STAGE\x10\x01\x12\x1e\n\x1aPROFILER_SKIP_UNWIND_STAGE\x10\x02\x12 \n\x1cPROFILER_SKIP_UNWIND_ENQUEUE\x10\x03\x42\x17\n\x15optional_unwind_errorB \n\x1eoptional_sample_skipped_reason"\x87\x01\n\x12PerfSampleDefaults\x12\x36\n\x08timebase\x18\x01 \x01(\x0b\x32$.perfetto.protos.PerfEvents.Timebase\x12\x1b\n\x13process_shard_count\x18\x02 \x01(\r\x12\x1c\n\x14\x63hosen_process_shard\x18\x03 \x01(\r"\x83\x03\n\nSmapsEntry\x12\x0c\n\x04path\x18\x01 \x01(\t\x12\x0f\n\x07size_kb\x18\x02 \x01(\x04\x12\x18\n\x10private_dirty_kb\x18\x03 \x01(\x04\x12\x0f\n\x07swap_kb\x18\x04 \x01(\x04\x12\x11\n\tfile_name\x18\x05 \x01(\t\x12\x15\n\rstart_address\x18\x06 \x01(\x04\x12\x18\n\x10module_timestamp\x18\x07 \x01(\x04\x12\x16\n\x0emodule_debugid\x18\x08 \x01(\t\x12\x19\n\x11module_debug_path\x18\t \x01(\t\x12\x18\n\x10protection_flags\x18\n \x01(\r\x12!\n\x19private_clean_resident_kb\x18\x0b \x01(\x04\x12 \n\x18shared_dirty_resident_kb\x18\x0c \x01(\x04\x12 \n\x18shared_clean_resident_kb\x18\r \x01(\x04\x12\x11\n\tlocked_kb\x18\x0e \x01(\x04\x12 \n\x18proportional_resident_kb\x18\x0f \x01(\x04"H\n\x0bSmapsPacket\x12\x0b\n\x03pid\x18\x01 \x01(\r\x12,\n\x07\x65ntries\x18\x02 \x03(\x0b\x32\x1b.perfetto.protos.SmapsEntry"\xa4\x06\n\x0cProcessStats\x12\x38\n\tprocesses\x18\x01 \x03(\x0b\x32%.perfetto.protos.ProcessStats.Process\x12 \n\x18\x63ollection_end_timestamp\x18\x02 \x01(\x04\x1a\'\n\x06Thread\x12\x0b\n\x03tid\x18\x01 \x01(\x05J\x04\x08\x02\x10\x03J\x04\x08\x03\x10\x04J\x04\x08\x04\x10\x05\x1a"\n\x06\x46\x44Info\x12\n\n\x02\x66\x64\x18\x01 \x01(\x04\x12\x0c\n\x04path\x18\x02 \x01(\t\x1a\xea\x04\n\x07Process\x12\x0b\n\x03pid\x18\x01 \x01(\x05\x12\x35\n\x07threads\x18\x0b \x03(\x0b\x32$.perfetto.protos.ProcessStats.Thread\x12\x12\n\nvm_size_kb\x18\x02 \x01(\x04\x12\x11\n\tvm_rss_kb\x18\x03 \x01(\x04\x12\x13\n\x0brss_anon_kb\x18\x04 \x01(\x04\x12\x13\n\x0brss_file_kb\x18\x05 \x01(\x04\x12\x14\n\x0crss_shmem_kb\x18\x06 \x01(\x04\x12\x12\n\nvm_swap_kb\x18\x07 \x01(\x04\x12\x14\n\x0cvm_locked_kb\x18\x08 \x01(\x04\x12\x11\n\tvm_hwm_kb\x18\t \x01(\x04\x12\x15\n\room_score_adj\x18\n \x01(\x03\x12\x1e\n\x16is_peak_rss_resettable\x18\x0c \x01(\x08\x12#\n\x1b\x63hrome_private_footprint_kb\x18\r \x01(\r\x12#\n\x1b\x63hrome_peak_resident_set_kb\x18\x0e \x01(\r\x12\x31\n\x03\x66\x64s\x18\x0f \x03(\x0b\x32$.perfetto.protos.ProcessStats.FDInfo\x12\x12\n\nsmr_rss_kb\x18\x10 \x01(\x04\x12\x12\n\nsmr_pss_kb\x18\x11 \x01(\x04\x12\x17\n\x0fsmr_pss_anon_kb\x18\x12 \x01(\x04\x12\x17\n\x0fsmr_pss_file_kb\x18\x13 \x01(\x04\x12\x18\n\x10smr_pss_shmem_kb\x18\x14 \x01(\x04\x12\x17\n\x0fsmr_swap_pss_kb\x18\x17 \x01(\x04\x12\x19\n\x11runtime_user_mode\x18\x15 \x01(\x04\x12\x1b\n\x13runtime_kernel_mode\x18\x16 \x01(\x04"\xda\x02\n\x0bProcessTree\x12\x37\n\tprocesses\x18\x01 \x03(\x0b\x32$.perfetto.protos.ProcessTree.Process\x12\x34\n\x07threads\x18\x02 \x03(\x0b\x32#.perfetto.protos.ProcessTree.Thread\x12 \n\x18\x63ollection_end_timestamp\x18\x03 \x01(\x04\x1a@\n\x06Thread\x12\x0b\n\x03tid\x18\x01 \x01(\x05\x12\x0c\n\x04tgid\x18\x03 \x01(\x05\x12\x0c\n\x04name\x18\x02 \x01(\t\x12\r\n\x05nstid\x18\x04 \x03(\x05\x1ax\n\x07Process\x12\x0b\n\x03pid\x18\x01 \x01(\x05\x12\x0c\n\x04ppid\x18\x02 \x01(\x05\x12\x0f\n\x07\x63mdline\x18\x03 \x03(\t\x12\x0b\n\x03uid\x18\x05 \x01(\x05\x12\r\n\x05nspid\x18\x06 \x03(\x05\x12\x1f\n\x17process_start_from_boot\x18\x07 \x01(\x04J\x04\x08\x04\x10\x05"\xd3\x01\n\x0fRemoteClockSync\x12\x44\n\rsynced_clocks\x18\x01 \x03(\x0b\x32-.perfetto.protos.RemoteClockSync.SyncedClocks\x1az\n\x0cSyncedClocks\x12\x35\n\rclient_clocks\x18\x02 \x01(\x0b\x32\x1e.perfetto.protos.ClockSnapshot\x12\x33\n\x0bhost_clocks\x18\x03 \x01(\x0b\x32\x1e.perfetto.protos.ClockSnapshot"\x06\n\x04\x41tom"J\n\nStatsdAtom\x12#\n\x04\x61tom\x18\x01 \x03(\x0b\x32\x15.perfetto.protos.Atom\x12\x17\n\x0ftimestamp_nanos\x18\x02 \x03(\x03"\xd6\x0f\n\x08SysStats\x12\x37\n\x07meminfo\x18\x01 \x03(\x0b\x32&.perfetto.protos.SysStats.MeminfoValue\x12\x35\n\x06vmstat\x18\x02 \x03(\x0b\x32%.perfetto.protos.SysStats.VmstatValue\x12\x34\n\x08\x63pu_stat\x18\x03 \x03(\x0b\x32".perfetto.protos.SysStats.CpuTimes\x12\x11\n\tnum_forks\x18\x04 \x01(\x04\x12\x15\n\rnum_irq_total\x18\x05 \x01(\x04\x12\x39\n\x07num_irq\x18\x06 \x03(\x0b\x32(.perfetto.protos.SysStats.InterruptCount\x12\x19\n\x11num_softirq_total\x18\x07 \x01(\x04\x12=\n\x0bnum_softirq\x18\x08 \x03(\x0b\x32(.perfetto.protos.SysStats.InterruptCount\x12 \n\x18\x63ollection_end_timestamp\x18\t \x01(\x04\x12\x37\n\x07\x64\x65vfreq\x18\n \x03(\x0b\x32&.perfetto.protos.SysStats.DevfreqValue\x12\x13\n\x0b\x63pufreq_khz\x18\x0b \x03(\r\x12\x37\n\nbuddy_info\x18\x0c \x03(\x0b\x32#.perfetto.protos.SysStats.BuddyInfo\x12\x35\n\tdisk_stat\x18\r \x03(\x0b\x32".perfetto.protos.SysStats.DiskStat\x12\x30\n\x03psi\x18\x0e \x03(\x0b\x32#.perfetto.protos.SysStats.PsiSample\x12;\n\x0cthermal_zone\x18\x0f \x03(\x0b\x32%.perfetto.protos.SysStats.ThermalZone\x12=\n\rcpuidle_state\x18\x10 \x03(\x0b\x32&.perfetto.protos.SysStats.CpuIdleState\x12\x13\n\x0bgpufreq_mhz\x18\x11 \x03(\x04\x1aL\n\x0cMeminfoValue\x12-\n\x03key\x18\x01 \x01(\x0e\x32 .perfetto.protos.MeminfoCounters\x12\r\n\x05value\x18\x02 \x01(\x04\x1aJ\n\x0bVmstatValue\x12,\n\x03key\x18\x01 \x01(\x0e\x32\x1f.perfetto.protos.VmstatCounters\x12\r\n\x05value\x18\x02 \x01(\x04\x1a\xa2\x01\n\x08\x43puTimes\x12\x0e\n\x06\x63pu_id\x18\x01 \x01(\r\x12\x0f\n\x07user_ns\x18\x02 \x01(\x04\x12\x14\n\x0cuser_nice_ns\x18\x03 \x01(\x04\x12\x16\n\x0esystem_mode_ns\x18\x04 \x01(\x04\x12\x0f\n\x07idle_ns\x18\x05 \x01(\x04\x12\x12\n\nio_wait_ns\x18\x06 \x01(\x04\x12\x0e\n\x06irq_ns\x18\x07 \x01(\x04\x12\x12\n\nsoftirq_ns\x18\x08 \x01(\x04\x1a,\n\x0eInterruptCount\x12\x0b\n\x03irq\x18\x01 \x01(\x05\x12\r\n\x05\x63ount\x18\x02 \x01(\x04\x1a*\n\x0c\x44\x65vfreqValue\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\x04\x1a<\n\tBuddyInfo\x12\x0c\n\x04node\x18\x01 \x01(\t\x12\x0c\n\x04zone\x18\x02 \x01(\t\x12\x13\n\x0border_pages\x18\x03 \x03(\r\x1a\xd7\x01\n\x08\x44iskStat\x12\x13\n\x0b\x64\x65vice_name\x18\x01 \x01(\t\x12\x14\n\x0cread_sectors\x18\x02 \x01(\x04\x12\x14\n\x0cread_time_ms\x18\x03 \x01(\x04\x12\x15\n\rwrite_sectors\x18\x04 \x01(\x04\x12\x15\n\rwrite_time_ms\x18\x05 \x01(\x04\x12\x17\n\x0f\x64iscard_sectors\x18\x06 \x01(\x04\x12\x17\n\x0f\x64iscard_time_ms\x18\x07 \x01(\x04\x12\x13\n\x0b\x66lush_count\x18\x08 \x01(\x04\x12\x15\n\rflush_time_ms\x18\t \x01(\x04\x1a\xb4\x02\n\tPsiSample\x12\x41\n\x08resource\x18\x01 \x01(\x0e\x32/.perfetto.protos.SysStats.PsiSample.PsiResource\x12\x10\n\x08total_ns\x18\x02 \x01(\x04"\xd1\x01\n\x0bPsiResource\x12\x1c\n\x18PSI_RESOURCE_UNSPECIFIED\x10\x00\x12\x19\n\x15PSI_RESOURCE_CPU_SOME\x10\x01\x12\x19\n\x15PSI_RESOURCE_CPU_FULL\x10\x02\x12\x18\n\x14PSI_RESOURCE_IO_SOME\x10\x03\x12\x18\n\x14PSI_RESOURCE_IO_FULL\x10\x04\x12\x1c\n\x18PSI_RESOURCE_MEMORY_SOME\x10\x05\x12\x1c\n\x18PSI_RESOURCE_MEMORY_FULL\x10\x06\x1a\x37\n\x0bThermalZone\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x0c\n\x04temp\x18\x02 \x01(\x04\x12\x0c\n\x04type\x18\x03 \x01(\t\x1a\x37\n\x11\x43puIdleStateEntry\x12\r\n\x05state\x18\x01 \x01(\t\x12\x13\n\x0b\x64uration_us\x18\x02 \x01(\x04\x1ah\n\x0c\x43puIdleState\x12\x0e\n\x06\x63pu_id\x18\x01 \x01(\r\x12H\n\x13\x63puidle_state_entry\x18\x02 \x03(\x0b\x32+.perfetto.protos.SysStats.CpuIdleStateEntry"M\n\x07Utsname\x12\x0f\n\x07sysname\x18\x01 \x01(\t\x12\x0f\n\x07version\x18\x02 \x01(\t\x12\x0f\n\x07release\x18\x03 \x01(\t\x12\x0f\n\x07machine\x18\x04 \x01(\t"\xdc\x02\n\nSystemInfo\x12)\n\x07utsname\x18\x01 \x01(\x0b\x32\x18.perfetto.protos.Utsname\x12!\n\x19\x61ndroid_build_fingerprint\x18\x02 \x01(\t\x12\x19\n\x11\x61ndroid_soc_model\x18\t \x01(\t\x12!\n\x19\x61ndroid_hardware_revision\x18\n \x01(\t\x12\x1d\n\x15\x61ndroid_storage_model\x18\x0b \x01(\t\x12\x19\n\x11\x61ndroid_ram_model\x18\x0c \x01(\t\x12\x1f\n\x17tracing_service_version\x18\x04 \x01(\t\x12\x1b\n\x13\x61ndroid_sdk_version\x18\x05 \x01(\x04\x12\x11\n\tpage_size\x18\x06 \x01(\r\x12\x10\n\x08num_cpus\x18\x08 \x01(\r\x12\x19\n\x11timezone_off_mins\x18\x07 \x01(\x05\x12\n\n\x02hz\x18\x03 \x01(\x03"v\n\x07\x43puInfo\x12*\n\x04\x63pus\x18\x01 \x03(\x0b\x32\x1c.perfetto.protos.CpuInfo.Cpu\x1a?\n\x03\x43pu\x12\x11\n\tprocessor\x18\x01 \x01(\t\x12\x13\n\x0b\x66requencies\x18\x02 \x03(\r\x12\x10\n\x08\x63\x61pacity\x18\x03 \x01(\r"\xfb\x02\n\tTestEvent\x12\x0b\n\x03str\x18\x01 \x01(\t\x12\x11\n\tseq_value\x18\x02 \x01(\r\x12\x0f\n\x07\x63ounter\x18\x03 \x01(\x04\x12\x0f\n\x07is_last\x18\x04 \x01(\x08\x12\x37\n\x07payload\x18\x05 \x01(\x0b\x32&.perfetto.protos.TestEvent.TestPayload\x1a\xf2\x01\n\x0bTestPayload\x12\x0b\n\x03str\x18\x01 \x03(\t\x12\x36\n\x06nested\x18\x02 \x03(\x0b\x32&.perfetto.protos.TestEvent.TestPayload\x12\x15\n\rsingle_string\x18\x04 \x01(\t\x12\x12\n\nsingle_int\x18\x05 \x01(\x05\x12\x15\n\rrepeated_ints\x18\x06 \x03(\x05\x12\x1f\n\x17remaining_nesting_depth\x18\x03 \x01(\r\x12;\n\x11\x64\x65\x62ug_annotations\x18\x07 \x03(\x0b\x32 .perfetto.protos.DebugAnnotation"\xf2\x01\n\x13TracePacketDefaults\x12\x1a\n\x12timestamp_clock_id\x18: \x01(\r\x12\x41\n\x14track_event_defaults\x18\x0b \x01(\x0b\x32#.perfetto.protos.TrackEventDefaults\x12\x41\n\x14perf_sample_defaults\x18\x0c \x01(\x0b\x32#.perfetto.protos.PerfSampleDefaults\x12\x39\n\x10v8_code_defaults\x18\x63 \x01(\x0b\x32\x1f.perfetto.protos.V8CodeDefaults"%\n\tTraceUuid\x12\x0b\n\x03msb\x18\x01 \x01(\x03\x12\x0b\n\x03lsb\x18\x02 \x01(\x03"\xe7\x03\n\x11ProcessDescriptor\x12\x0b\n\x03pid\x18\x01 \x01(\x05\x12\x0f\n\x07\x63mdline\x18\x02 \x03(\t\x12\x14\n\x0cprocess_name\x18\x06 \x01(\t\x12\x18\n\x10process_priority\x18\x05 \x01(\x05\x12\x1a\n\x12start_timestamp_ns\x18\x07 \x01(\x03\x12Q\n\x13\x63hrome_process_type\x18\x04 \x01(\x0e\x32\x34.perfetto.protos.ProcessDescriptor.ChromeProcessType\x12\x19\n\x11legacy_sort_index\x18\x03 \x01(\x05\x12\x16\n\x0eprocess_labels\x18\x08 \x03(\t"\xe1\x01\n\x11\x43hromeProcessType\x12\x17\n\x13PROCESS_UNSPECIFIED\x10\x00\x12\x13\n\x0fPROCESS_BROWSER\x10\x01\x12\x14\n\x10PROCESS_RENDERER\x10\x02\x12\x13\n\x0fPROCESS_UTILITY\x10\x03\x12\x12\n\x0ePROCESS_ZYGOTE\x10\x04\x12\x1a\n\x16PROCESS_SANDBOX_HELPER\x10\x05\x12\x0f\n\x0bPROCESS_GPU\x10\x06\x12\x18\n\x14PROCESS_PPAPI_PLUGIN\x10\x07\x12\x18\n\x14PROCESS_PPAPI_BROKER\x10\x08"-\n\x19TrackEventRangeOfInterest\x12\x10\n\x08start_us\x18\x01 \x01(\x03"\xf4\x05\n\x10ThreadDescriptor\x12\x0b\n\x03pid\x18\x01 \x01(\x05\x12\x0b\n\x03tid\x18\x02 \x01(\x05\x12\x13\n\x0bthread_name\x18\x05 \x01(\t\x12N\n\x12\x63hrome_thread_type\x18\x04 \x01(\x0e\x32\x32.perfetto.protos.ThreadDescriptor.ChromeThreadType\x12\x1e\n\x16reference_timestamp_us\x18\x06 \x01(\x03\x12 \n\x18reference_thread_time_us\x18\x07 \x01(\x03\x12*\n"reference_thread_instruction_count\x18\x08 \x01(\x03\x12\x19\n\x11legacy_sort_index\x18\x03 \x01(\x05"\xd7\x03\n\x10\x43hromeThreadType\x12\x1d\n\x19\x43HROME_THREAD_UNSPECIFIED\x10\x00\x12\x16\n\x12\x43HROME_THREAD_MAIN\x10\x01\x12\x14\n\x10\x43HROME_THREAD_IO\x10\x02\x12 \n\x1c\x43HROME_THREAD_POOL_BG_WORKER\x10\x03\x12 \n\x1c\x43HROME_THREAD_POOL_FG_WORKER\x10\x04\x12"\n\x1e\x43HROME_THREAD_POOL_FB_BLOCKING\x10\x05\x12"\n\x1e\x43HROME_THREAD_POOL_BG_BLOCKING\x10\x06\x12\x1e\n\x1a\x43HROME_THREAD_POOL_SERVICE\x10\x07\x12\x1c\n\x18\x43HROME_THREAD_COMPOSITOR\x10\x08\x12 \n\x1c\x43HROME_THREAD_VIZ_COMPOSITOR\x10\t\x12#\n\x1f\x43HROME_THREAD_COMPOSITOR_WORKER\x10\n\x12 \n\x1c\x43HROME_THREAD_SERVICE_WORKER\x10\x0b\x12\x1e\n\x1a\x43HROME_THREAD_MEMORY_INFRA\x10\x32\x12#\n\x1f\x43HROME_THREAD_SAMPLING_PROFILER\x10\x33"\xe5\x0b\n\x17\x43hromeProcessDescriptor\x12J\n\x0cprocess_type\x18\x01 \x01(\x0e\x32\x34.perfetto.protos.ChromeProcessDescriptor.ProcessType\x12\x18\n\x10process_priority\x18\x02 \x01(\x05\x12\x19\n\x11legacy_sort_index\x18\x03 \x01(\x05\x12\x1d\n\x15host_app_package_name\x18\x04 \x01(\t\x12\x16\n\x0e\x63rash_trace_id\x18\x05 \x01(\x04"\x91\n\n\x0bProcessType\x12\x17\n\x13PROCESS_UNSPECIFIED\x10\x00\x12\x13\n\x0fPROCESS_BROWSER\x10\x01\x12\x14\n\x10PROCESS_RENDERER\x10\x02\x12\x13\n\x0fPROCESS_UTILITY\x10\x03\x12\x12\n\x0ePROCESS_ZYGOTE\x10\x04\x12\x1a\n\x16PROCESS_SANDBOX_HELPER\x10\x05\x12\x0f\n\x0bPROCESS_GPU\x10\x06\x12\x18\n\x14PROCESS_PPAPI_PLUGIN\x10\x07\x12\x18\n\x14PROCESS_PPAPI_BROKER\x10\x08\x12\x1b\n\x17PROCESS_SERVICE_NETWORK\x10\t\x12\x1b\n\x17PROCESS_SERVICE_TRACING\x10\n\x12\x1b\n\x17PROCESS_SERVICE_STORAGE\x10\x0b\x12\x19\n\x15PROCESS_SERVICE_AUDIO\x10\x0c\x12 \n\x1cPROCESS_SERVICE_DATA_DECODER\x10\r\x12\x1c\n\x18PROCESS_SERVICE_UTIL_WIN\x10\x0e\x12"\n\x1ePROCESS_SERVICE_PROXY_RESOLVER\x10\x0f\x12\x17\n\x13PROCESS_SERVICE_CDM\x10\x10\x12!\n\x1dPROCESS_SERVICE_VIDEO_CAPTURE\x10\x11\x12\x1c\n\x18PROCESS_SERVICE_UNZIPPER\x10\x12\x12\x1d\n\x19PROCESS_SERVICE_MIRRORING\x10\x13\x12\x1f\n\x1bPROCESS_SERVICE_FILEPATCHER\x10\x14\x12\x17\n\x13PROCESS_SERVICE_TTS\x10\x15\x12\x1c\n\x18PROCESS_SERVICE_PRINTING\x10\x16\x12\x1e\n\x1aPROCESS_SERVICE_QUARANTINE\x10\x17\x12$\n PROCESS_SERVICE_CROS_LOCALSEARCH\x10\x18\x12\x30\n,PROCESS_SERVICE_CROS_ASSISTANT_AUDIO_DECODER\x10\x19\x12\x1c\n\x18PROCESS_SERVICE_FILEUTIL\x10\x1a\x12#\n\x1fPROCESS_SERVICE_PRINTCOMPOSITOR\x10\x1b\x12 \n\x1cPROCESS_SERVICE_PAINTPREVIEW\x10\x1c\x12%\n!PROCESS_SERVICE_SPEECHRECOGNITION\x10\x1d\x12\x1c\n\x18PROCESS_SERVICE_XRDEVICE\x10\x1e\x12\x1c\n\x18PROCESS_SERVICE_READICON\x10\x1f\x12%\n!PROCESS_SERVICE_LANGUAGEDETECTION\x10 \x12\x1b\n\x17PROCESS_SERVICE_SHARING\x10!\x12\x1f\n\x1bPROCESS_SERVICE_MEDIAPARSER\x10"\x12#\n\x1fPROCESS_SERVICE_QRCODEGENERATOR\x10#\x12!\n\x1dPROCESS_SERVICE_PROFILEIMPORT\x10$\x12\x17\n\x13PROCESS_SERVICE_IME\x10%\x12\x1d\n\x19PROCESS_SERVICE_RECORDING\x10&\x12"\n\x1ePROCESS_SERVICE_SHAPEDETECTION\x10\'\x12\x1e\n\x1aPROCESS_RENDERER_EXTENSION\x10(\x12$\n PROCESS_SERVICE_MEDIA_FOUNDATION\x10)"\xec\t\n\x16\x43hromeThreadDescriptor\x12G\n\x0bthread_type\x18\x01 \x01(\x0e\x32\x32.perfetto.protos.ChromeThreadDescriptor.ThreadType\x12\x19\n\x11legacy_sort_index\x18\x02 \x01(\x05"\xed\x08\n\nThreadType\x12\x16\n\x12THREAD_UNSPECIFIED\x10\x00\x12\x0f\n\x0bTHREAD_MAIN\x10\x01\x12\r\n\tTHREAD_IO\x10\x02\x12\x19\n\x15THREAD_POOL_BG_WORKER\x10\x03\x12\x19\n\x15THREAD_POOL_FG_WORKER\x10\x04\x12\x1b\n\x17THREAD_POOL_FG_BLOCKING\x10\x05\x12\x1b\n\x17THREAD_POOL_BG_BLOCKING\x10\x06\x12\x17\n\x13THREAD_POOL_SERVICE\x10\x07\x12\x15\n\x11THREAD_COMPOSITOR\x10\x08\x12\x19\n\x15THREAD_VIZ_COMPOSITOR\x10\t\x12\x1c\n\x18THREAD_COMPOSITOR_WORKER\x10\n\x12\x19\n\x15THREAD_SERVICE_WORKER\x10\x0b\x12\x1a\n\x16THREAD_NETWORK_SERVICE\x10\x0c\x12\x13\n\x0fTHREAD_CHILD_IO\x10\r\x12\x15\n\x11THREAD_BROWSER_IO\x10\x0e\x12\x17\n\x13THREAD_BROWSER_MAIN\x10\x0f\x12\x18\n\x14THREAD_RENDERER_MAIN\x10\x10\x12\x17\n\x13THREAD_UTILITY_MAIN\x10\x11\x12\x13\n\x0fTHREAD_GPU_MAIN\x10\x12\x12\x1a\n\x16THREAD_CACHE_BLOCKFILE\x10\x13\x12\x10\n\x0cTHREAD_MEDIA\x10\x14\x12\x1d\n\x19THREAD_AUDIO_OUTPUTDEVICE\x10\x15\x12\x1c\n\x18THREAD_AUDIO_INPUTDEVICE\x10\x16\x12\x15\n\x11THREAD_GPU_MEMORY\x10\x17\x12\x14\n\x10THREAD_GPU_VSYNC\x10\x18\x12\x1b\n\x17THREAD_DXA_VIDEODECODER\x10\x19\x12\x1b\n\x17THREAD_BROWSER_WATCHDOG\x10\x1a\x12\x19\n\x15THREAD_WEBRTC_NETWORK\x10\x1b\x12\x17\n\x13THREAD_WINDOW_OWNER\x10\x1c\x12\x1b\n\x17THREAD_WEBRTC_SIGNALING\x10\x1d\x12\x18\n\x14THREAD_WEBRTC_WORKER\x10\x1e\x12\x15\n\x11THREAD_PPAPI_MAIN\x10\x1f\x12\x17\n\x13THREAD_GPU_WATCHDOG\x10 \x12\x12\n\x0eTHREAD_SWAPPER\x10!\x12\x1a\n\x16THREAD_GAMEPAD_POLLING\x10"\x12\x14\n\x10THREAD_WEBCRYPTO\x10#\x12\x13\n\x0fTHREAD_DATABASE\x10$\x12\x18\n\x14THREAD_PROXYRESOLVER\x10%\x12\x16\n\x12THREAD_DEVTOOLSADB\x10&\x12\x1f\n\x1bTHREAD_NETWORKCONFIGWATCHER\x10\'\x12\x18\n\x14THREAD_WASAPI_RENDER\x10(\x12\x1e\n\x1aTHREAD_LOADER_LOCK_SAMPLER\x10)\x12\x17\n\x13THREAD_MEMORY_INFRA\x10\x32\x12\x1c\n\x18THREAD_SAMPLING_PROFILER\x10\x33"\xad\x03\n\x11\x43ounterDescriptor\x12\x43\n\x04type\x18\x01 \x01(\x0e\x32\x35.perfetto.protos.CounterDescriptor.BuiltinCounterType\x12\x12\n\ncategories\x18\x02 \x03(\t\x12\x35\n\x04unit\x18\x03 \x01(\x0e\x32\'.perfetto.protos.CounterDescriptor.Unit\x12\x11\n\tunit_name\x18\x06 \x01(\t\x12\x17\n\x0funit_multiplier\x18\x04 \x01(\x03\x12\x16\n\x0eis_incremental\x18\x05 \x01(\x08"o\n\x12\x42uiltinCounterType\x12\x17\n\x13\x43OUNTER_UNSPECIFIED\x10\x00\x12\x1a\n\x16\x43OUNTER_THREAD_TIME_NS\x10\x01\x12$\n COUNTER_THREAD_INSTRUCTION_COUNT\x10\x02"S\n\x04Unit\x12\x14\n\x10UNIT_UNSPECIFIED\x10\x00\x12\x10\n\x0cUNIT_TIME_NS\x10\x01\x12\x0e\n\nUNIT_COUNT\x10\x02\x12\x13\n\x0fUNIT_SIZE_BYTES\x10\x03"\xc1\x03\n\x0fTrackDescriptor\x12\x0c\n\x04uuid\x18\x01 \x01(\x04\x12\x13\n\x0bparent_uuid\x18\x05 \x01(\x04\x12\x0e\n\x04name\x18\x02 \x01(\tH\x00\x12\x15\n\x0bstatic_name\x18\n \x01(\tH\x00\x12\x33\n\x07process\x18\x03 \x01(\x0b\x32".perfetto.protos.ProcessDescriptor\x12@\n\x0e\x63hrome_process\x18\x06 \x01(\x0b\x32(.perfetto.protos.ChromeProcessDescriptor\x12\x31\n\x06thread\x18\x04 \x01(\x0b\x32!.perfetto.protos.ThreadDescriptor\x12>\n\rchrome_thread\x18\x07 \x01(\x0b\x32\'.perfetto.protos.ChromeThreadDescriptor\x12\x33\n\x07\x63ounter\x18\x08 \x01(\x0b\x32".perfetto.protos.CounterDescriptor\x12+\n#disallow_merging_with_system_tracks\x18\t \x01(\x08\x42\x18\n\x16static_or_dynamic_name"\xa7\x03\n\x10TranslationTable\x12M\n\x10\x63hrome_histogram\x18\x01 \x01(\x0b\x32\x31.perfetto.protos.ChromeHistorgramTranslationTableH\x00\x12M\n\x11\x63hrome_user_event\x18\x02 \x01(\x0b\x32\x30.perfetto.protos.ChromeUserEventTranslationTableH\x00\x12Y\n\x17\x63hrome_performance_mark\x18\x03 \x01(\x0b\x32\x36.perfetto.protos.ChromePerformanceMarkTranslationTableH\x00\x12@\n\nslice_name\x18\x04 \x01(\x0b\x32*.perfetto.protos.SliceNameTranslationTableH\x00\x12O\n\x12process_track_name\x18\x05 \x01(\x0b\x32\x31.perfetto.protos.ProcessTrackNameTranslationTableH\x00\x42\x07\n\x05table"\xae\x01\n ChromeHistorgramTranslationTable\x12W\n\x0chash_to_name\x18\x01 \x03(\x0b\x32\x41.perfetto.protos.ChromeHistorgramTranslationTable.HashToNameEntry\x1a\x31\n\x0fHashToNameEntry\x12\x0b\n\x03key\x18\x01 \x01(\x04\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01"\xbf\x01\n\x1f\x43hromeUserEventTranslationTable\x12\x63\n\x13\x61\x63tion_hash_to_name\x18\x01 \x03(\x0b\x32\x46.perfetto.protos.ChromeUserEventTranslationTable.ActionHashToNameEntry\x1a\x37\n\x15\x41\x63tionHashToNameEntry\x12\x0b\n\x03key\x18\x01 \x01(\x04\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01"\xe3\x02\n%ChromePerformanceMarkTranslationTable\x12\x65\n\x11site_hash_to_name\x18\x01 \x03(\x0b\x32J.perfetto.protos.ChromePerformanceMarkTranslationTable.SiteHashToNameEntry\x12\x65\n\x11mark_hash_to_name\x18\x02 \x03(\x0b\x32J.perfetto.protos.ChromePerformanceMarkTranslationTable.MarkHashToNameEntry\x1a\x35\n\x13SiteHashToNameEntry\x12\x0b\n\x03key\x18\x01 \x01(\r\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\x1a\x35\n\x13MarkHashToNameEntry\x12\x0b\n\x03key\x18\x01 \x01(\r\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01"\xc2\x01\n\x19SliceNameTranslationTable\x12g\n\x18raw_to_deobfuscated_name\x18\x01 \x03(\x0b\x32\x45.perfetto.protos.SliceNameTranslationTable.RawToDeobfuscatedNameEntry\x1a<\n\x1aRawToDeobfuscatedNameEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01"\xd0\x01\n ProcessTrackNameTranslationTable\x12n\n\x18raw_to_deobfuscated_name\x18\x01 \x03(\x0b\x32L.perfetto.protos.ProcessTrackNameTranslationTable.RawToDeobfuscatedNameEntry\x1a<\n\x1aRawToDeobfuscatedNameEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01"T\n\x07Trigger\x12\x14\n\x0ctrigger_name\x18\x01 \x01(\t\x12\x15\n\rproducer_name\x18\x02 \x01(\t\x12\x1c\n\x14trusted_producer_uid\x18\x03 \x01(\x05"\xc5\x01\n\x07UiState\x12\x19\n\x11timeline_start_ts\x18\x01 \x01(\x03\x12\x17\n\x0ftimeline_end_ts\x18\x02 \x01(\x03\x12\x44\n\x11highlight_process\x18\x03 \x01(\x0b\x32).perfetto.protos.UiState.HighlightProcess\x1a@\n\x10HighlightProcess\x12\r\n\x03pid\x18\x01 \x01(\rH\x00\x12\x11\n\x07\x63mdline\x18\x02 \x01(\tH\x00\x42\n\n\x08selector"\x90+\n\x0bTracePacket\x12\x11\n\ttimestamp\x18\x08 \x01(\x04\x12\x1a\n\x12timestamp_clock_id\x18: \x01(\r\x12\x34\n\x0cprocess_tree\x18\x02 \x01(\x0b\x32\x1c.perfetto.protos.ProcessTreeH\x00\x12\x36\n\rprocess_stats\x18\t \x01(\x0b\x32\x1d.perfetto.protos.ProcessStatsH\x00\x12\x37\n\x0einode_file_map\x18\x04 \x01(\x0b\x32\x1d.perfetto.protos.InodeFileMapH\x00\x12;\n\rchrome_events\x18\x05 \x01(\x0b\x32".perfetto.protos.ChromeEventBundleH\x00\x12\x38\n\x0e\x63lock_snapshot\x18\x06 \x01(\x0b\x32\x1e.perfetto.protos.ClockSnapshotH\x00\x12.\n\tsys_stats\x18\x07 \x01(\x0b\x32\x19.perfetto.protos.SysStatsH\x00\x12\x32\n\x0btrack_event\x18\x0b \x01(\x0b\x32\x1b.perfetto.protos.TrackEventH\x00\x12\x30\n\ntrace_uuid\x18Y \x01(\x0b\x32\x1a.perfetto.protos.TraceUuidH\x00\x12\x34\n\x0ctrace_config\x18! \x01(\x0b\x32\x1c.perfetto.protos.TraceConfigH\x00\x12\x34\n\x0c\x66trace_stats\x18" \x01(\x0b\x32\x1c.perfetto.protos.FtraceStatsH\x00\x12\x32\n\x0btrace_stats\x18# \x01(\x0b\x32\x1b.perfetto.protos.TraceStatsH\x00\x12\x38\n\x0eprofile_packet\x18% \x01(\x0b\x32\x1e.perfetto.protos.ProfilePacketH\x00\x12\x44\n\x14streaming_allocation\x18J \x01(\x0b\x32$.perfetto.protos.StreamingAllocationH\x00\x12\x38\n\x0estreaming_free\x18K \x01(\x0b\x32\x1e.perfetto.protos.StreamingFreeH\x00\x12\x33\n\x07\x62\x61ttery\x18& \x01(\x0b\x32 .perfetto.protos.BatteryCountersH\x00\x12\x32\n\x0bpower_rails\x18( \x01(\x0b\x32\x1b.perfetto.protos.PowerRailsH\x00\x12\x38\n\x0b\x61ndroid_log\x18\' \x01(\x0b\x32!.perfetto.protos.AndroidLogPacketH\x00\x12\x32\n\x0bsystem_info\x18- \x01(\x0b\x32\x1b.perfetto.protos.SystemInfoH\x00\x12+\n\x07trigger\x18. \x01(\x0b\x32\x18.perfetto.protos.TriggerH\x00\x12\x38\n\x0e\x63hrome_trigger\x18m \x01(\x0b\x32\x1e.perfetto.protos.ChromeTriggerH\x00\x12\x36\n\rpackages_list\x18/ \x01(\x0b\x32\x1d.perfetto.protos.PackagesListH\x00\x12M\n\x19\x63hrome_benchmark_metadata\x18\x30 \x01(\x0b\x32(.perfetto.protos.ChromeBenchmarkMetadataH\x00\x12@\n\x12perfetto_metatrace\x18\x31 \x01(\x0b\x32".perfetto.protos.PerfettoMetatraceH\x00\x12@\n\x0f\x63hrome_metadata\x18\x33 \x01(\x0b\x32%.perfetto.protos.ChromeMetadataPacketH\x00\x12=\n\x11gpu_counter_event\x18\x34 \x01(\x0b\x32 .perfetto.protos.GpuCounterEventH\x00\x12\x46\n\x16gpu_render_stage_event\x18\x35 \x01(\x0b\x32$.perfetto.protos.GpuRenderStageEventH\x00\x12K\n\x18streaming_profile_packet\x18\x36 \x01(\x0b\x32\'.perfetto.protos.StreamingProfilePacketH\x00\x12\x30\n\nheap_graph\x18\x38 \x01(\x0b\x32\x1a.perfetto.protos.HeapGraphH\x00\x12\x43\n\x14graphics_frame_event\x18\x39 \x01(\x0b\x32#.perfetto.protos.GraphicsFrameEventH\x00\x12\x41\n\x13vulkan_memory_event\x18> \x01(\x0b\x32".perfetto.protos.VulkanMemoryEventH\x00\x12*\n\x07gpu_log\x18? \x01(\x0b\x32\x17.perfetto.protos.GpuLogH\x00\x12;\n\x10vulkan_api_event\x18\x41 \x01(\x0b\x32\x1f.perfetto.protos.VulkanApiEventH\x00\x12\x32\n\x0bperf_sample\x18\x42 \x01(\x0b\x32\x1b.perfetto.protos.PerfSampleH\x00\x12,\n\x08\x63pu_info\x18\x43 \x01(\x0b\x32\x18.perfetto.protos.CpuInfoH\x00\x12\x34\n\x0csmaps_packet\x18\x44 \x01(\x0b\x32\x1c.perfetto.protos.SmapsPacketH\x00\x12=\n\rservice_event\x18\x45 \x01(\x0b\x32$.perfetto.protos.TracingServiceEventH\x00\x12\x45\n\x15initial_display_state\x18\x46 \x01(\x0b\x32$.perfetto.protos.InitialDisplayStateH\x00\x12@\n\x13gpu_mem_total_event\x18G \x01(\x0b\x32!.perfetto.protos.GpuMemTotalEventH\x00\x12I\n\x17memory_tracker_snapshot\x18I \x01(\x0b\x32&.perfetto.protos.MemoryTrackerSnapshotH\x00\x12\x43\n\x14\x66rame_timeline_event\x18L \x01(\x0b\x32#.perfetto.protos.FrameTimelineEventH\x00\x12`\n#android_energy_estimation_breakdown\x18M \x01(\x0b\x32\x31.perfetto.protos.AndroidEnergyEstimationBreakdownH\x00\x12,\n\x08ui_state\x18N \x01(\x0b\x32\x18.perfetto.protos.UiStateH\x00\x12N\n\x1a\x61ndroid_camera_frame_event\x18P \x01(\x0b\x32(.perfetto.protos.AndroidCameraFrameEventH\x00\x12R\n\x1c\x61ndroid_camera_session_stats\x18Q \x01(\x0b\x32*.perfetto.protos.AndroidCameraSessionStatsH\x00\x12>\n\x11translation_table\x18R \x01(\x0b\x32!.perfetto.protos.TranslationTableH\x00\x12V\n\x1e\x61ndroid_game_intervention_list\x18S \x01(\x0b\x32,.perfetto.protos.AndroidGameInterventionListH\x00\x12\x32\n\x0bstatsd_atom\x18T \x01(\x0b\x32\x1b.perfetto.protos.StatsdAtomH\x00\x12I\n\x17\x61ndroid_system_property\x18V \x01(\x0b\x32&.perfetto.protos.AndroidSystemPropertyH\x00\x12G\n\x16\x65ntity_state_residency\x18[ \x01(\x0b\x32%.perfetto.protos.EntityStateResidencyH\x00\x12G\n\x16profiled_frame_symbols\x18\x37 \x01(\x0b\x32%.perfetto.protos.ProfiledFrameSymbolsH\x00\x12\x38\n\x0emodule_symbols\x18= \x01(\x0b\x32\x1e.perfetto.protos.ModuleSymbolsH\x00\x12\x46\n\x15\x64\x65obfuscation_mapping\x18@ \x01(\x0b\x32%.perfetto.protos.DeobfuscationMappingH\x00\x12<\n\x10track_descriptor\x18< \x01(\x0b\x32 .perfetto.protos.TrackDescriptorH\x00\x12@\n\x12process_descriptor\x18+ \x01(\x0b\x32".perfetto.protos.ProcessDescriptorH\x00\x12>\n\x11thread_descriptor\x18, \x01(\x0b\x32!.perfetto.protos.ThreadDescriptorH\x00\x12;\n\rftrace_events\x18\x01 \x01(\x0b\x32".perfetto.protos.FtraceEventBundleH\x00\x12 \n\x16synchronization_marker\x18$ \x01(\x0cH\x00\x12\x1c\n\x12\x63ompressed_packets\x18\x32 \x01(\x0cH\x00\x12\x44\n\x14\x65xtension_descriptor\x18H \x01(\x0b\x32$.perfetto.protos.ExtensionDescriptorH\x00\x12=\n\x0enetwork_packet\x18X \x01(\x0b\x32#.perfetto.protos.NetworkPacketEventH\x00\x12\x45\n\x15network_packet_bundle\x18\\ \x01(\x0b\x32$.perfetto.protos.NetworkPacketBundleH\x00\x12S\n\x1dtrack_event_range_of_interest\x18Z \x01(\x0b\x32*.perfetto.protos.TrackEventRangeOfInterestH\x00\x12N\n\x1esurfaceflinger_layers_snapshot\x18] \x01(\x0b\x32$.perfetto.protos.LayersSnapshotProtoH\x00\x12M\n\x1bsurfaceflinger_transactions\x18^ \x01(\x0b\x32&.perfetto.protos.TransactionTraceEntryH\x00\x12<\n\x10shell_transition\x18` \x01(\x0b\x32 .perfetto.protos.ShellTransitionH\x00\x12G\n\x16shell_handler_mappings\x18\x61 \x01(\x0b\x32%.perfetto.protos.ShellHandlerMappingsH\x00\x12<\n\x10protolog_message\x18h \x01(\x0b\x32 .perfetto.protos.ProtoLogMessageH\x00\x12G\n\x16protolog_viewer_config\x18i \x01(\x0b\x32%.perfetto.protos.ProtoLogViewerConfigH\x00\x12\x42\n\x13winscope_extensions\x18p \x01(\x0b\x32#.perfetto.protos.WinscopeExtensionsH\x00\x12:\n\netw_events\x18_ \x01(\x0b\x32$.perfetto.protos.EtwTraceEventBundleH\x00\x12/\n\nv8_js_code\x18\x63 \x01(\x0b\x32\x19.perfetto.protos.V8JsCodeH\x00\x12;\n\x10v8_internal_code\x18\x64 \x01(\x0b\x32\x1f.perfetto.protos.V8InternalCodeH\x00\x12\x33\n\x0cv8_wasm_code\x18\x65 \x01(\x0b\x32\x1b.perfetto.protos.V8WasmCodeH\x00\x12\x38\n\x0fv8_reg_exp_code\x18\x66 \x01(\x0b\x32\x1d.perfetto.protos.V8RegExpCodeH\x00\x12\x33\n\x0cv8_code_move\x18g \x01(\x0b\x32\x1b.perfetto.protos.V8CodeMoveH\x00\x12=\n\x11remote_clock_sync\x18k \x01(\x0b\x32 .perfetto.protos.RemoteClockSyncH\x00\x12?\n\x12pixel_modem_events\x18n \x01(\x0b\x32!.perfetto.protos.PixelModemEventsH\x00\x12N\n\x1apixel_modem_token_database\x18o \x01(\x0b\x32(.perfetto.protos.PixelModemTokenDatabaseH\x00\x12\x32\n\x0b\x66or_testing\x18\x84\x07 \x01(\x0b\x32\x1a.perfetto.protos.TestEventH\x00\x12\x15\n\x0btrusted_uid\x18\x03 \x01(\x05H\x01\x12$\n\x1atrusted_packet_sequence_id\x18\n \x01(\rH\x02\x12\x13\n\x0btrusted_pid\x18O \x01(\x05\x12\x34\n\rinterned_data\x18\x0c \x01(\x0b\x32\x1d.perfetto.protos.InternedData\x12\x16\n\x0esequence_flags\x18\r \x01(\r\x12!\n\x19incremental_state_cleared\x18) \x01(\x08\x12\x43\n\x15trace_packet_defaults\x18; \x01(\x0b\x32$.perfetto.protos.TracePacketDefaults\x12\x1f\n\x17previous_packet_dropped\x18* \x01(\x08\x12 \n\x18\x66irst_packet_on_sequence\x18W \x01(\x08\x12\x12\n\nmachine_id\x18\x62 \x01(\r"h\n\rSequenceFlags\x12\x13\n\x0fSEQ_UNSPECIFIED\x10\x00\x12!\n\x1dSEQ_INCREMENTAL_STATE_CLEARED\x10\x01\x12\x1f\n\x1bSEQ_NEEDS_INCREMENTAL_STATE\x10\x02\x42\x06\n\x04\x64\x61taB\x16\n\x14optional_trusted_uidB%\n#optional_trusted_packet_sequence_idJ\x04\x08j\x10k"5\n\x05Trace\x12,\n\x06packet\x18\x01 \x03(\x0b\x32\x1c.perfetto.protos.TracePacket*\xa3\x02\n\x0c\x42uiltinClock\x12\x19\n\x15\x42UILTIN_CLOCK_UNKNOWN\x10\x00\x12\x1a\n\x16\x42UILTIN_CLOCK_REALTIME\x10\x01\x12!\n\x1d\x42UILTIN_CLOCK_REALTIME_COARSE\x10\x02\x12\x1b\n\x17\x42UILTIN_CLOCK_MONOTONIC\x10\x03\x12"\n\x1e\x42UILTIN_CLOCK_MONOTONIC_COARSE\x10\x04\x12\x1f\n\x1b\x42UILTIN_CLOCK_MONOTONIC_RAW\x10\x05\x12\x1a\n\x16\x42UILTIN_CLOCK_BOOTTIME\x10\x06\x12\x15\n\x11\x42UILTIN_CLOCK_TSC\x10\t\x12\x18\n\x14\x42UILTIN_CLOCK_MAX_ID\x10?"\x04\x08\x07\x10\x07"\x04\x08\x08\x10\x08*\x8e\x01\n\x0c\x41ndroidLogId\x12\x0f\n\x0bLID_DEFAULT\x10\x00\x12\r\n\tLID_RADIO\x10\x01\x12\x0e\n\nLID_EVENTS\x10\x02\x12\x0e\n\nLID_SYSTEM\x10\x03\x12\r\n\tLID_CRASH\x10\x04\x12\r\n\tLID_STATS\x10\x05\x12\x10\n\x0cLID_SECURITY\x10\x06\x12\x0e\n\nLID_KERNEL\x10\x07*\x9b\x01\n\x12\x41ndroidLogPriority\x12\x14\n\x10PRIO_UNSPECIFIED\x10\x00\x12\x0f\n\x0bPRIO_UNUSED\x10\x01\x12\x10\n\x0cPRIO_VERBOSE\x10\x02\x12\x0e\n\nPRIO_DEBUG\x10\x03\x12\r\n\tPRIO_INFO\x10\x04\x12\r\n\tPRIO_WARN\x10\x05\x12\x0e\n\nPRIO_ERROR\x10\x06\x12\x0e\n\nPRIO_FATAL\x10\x07*\xc7\x01\n\rProtoLogLevel\x12\x1c\n\x18PROTOLOG_LEVEL_UNDEFINED\x10\x00\x12\x18\n\x14PROTOLOG_LEVEL_DEBUG\x10\x01\x12\x1a\n\x16PROTOLOG_LEVEL_VERBOSE\x10\x02\x12\x17\n\x13PROTOLOG_LEVEL_INFO\x10\x03\x12\x17\n\x13PROTOLOG_LEVEL_WARN\x10\x04\x12\x18\n\x14PROTOLOG_LEVEL_ERROR\x10\x05\x12\x16\n\x12PROTOLOG_LEVEL_WTF\x10\x06*\xd2\x8e\x02\n\x06\x41tomId\x12\x14\n\x10\x41TOM_UNSPECIFIED\x10\x00\x12\x1f\n\x1b\x41TOM_BLE_SCAN_STATE_CHANGED\x10\x02\x12\x1e\n\x1a\x41TOM_PROCESS_STATE_CHANGED\x10\x03\x12!\n\x1d\x41TOM_BLE_SCAN_RESULT_RECEIVED\x10\x04\x12\x1d\n\x19\x41TOM_SENSOR_STATE_CHANGED\x10\x05\x12\x1f\n\x1b\x41TOM_GPS_SCAN_STATE_CHANGED\x10\x06\x12\x1b\n\x17\x41TOM_SYNC_STATE_CHANGED\x10\x07\x12$\n ATOM_SCHEDULED_JOB_STATE_CHANGED\x10\x08\x12"\n\x1e\x41TOM_SCREEN_BRIGHTNESS_CHANGED\x10\t\x12\x1f\n\x1b\x41TOM_WAKELOCK_STATE_CHANGED\x10\n\x12,\n(ATOM_LONG_PARTIAL_WAKELOCK_STATE_CHANGED\x10\x0b\x12)\n%ATOM_MOBILE_RADIO_POWER_STATE_CHANGED\x10\x0c\x12\'\n#ATOM_WIFI_RADIO_POWER_STATE_CHANGED\x10\r\x12-\n)ATOM_ACTIVITY_MANAGER_SLEEP_STATE_CHANGED\x10\x0e\x12$\n ATOM_MEMORY_FACTOR_STATE_CHANGED\x10\x0f\x12%\n!ATOM_EXCESSIVE_CPU_USAGE_REPORTED\x10\x10\x12\x1d\n\x19\x41TOM_CACHED_KILL_REPORTED\x10\x11\x12%\n!ATOM_PROCESS_MEMORY_STAT_REPORTED\x10\x12\x12\x17\n\x13\x41TOM_LAUNCHER_EVENT\x10\x13\x12)\n%ATOM_BATTERY_SAVER_MODE_STATE_CHANGED\x10\x14\x12\'\n#ATOM_DEVICE_IDLE_MODE_STATE_CHANGED\x10\x15\x12)\n%ATOM_DEVICE_IDLING_MODE_STATE_CHANGED\x10\x16\x12\x1c\n\x18\x41TOM_AUDIO_STATE_CHANGED\x10\x17\x12"\n\x1e\x41TOM_MEDIA_CODEC_STATE_CHANGED\x10\x18\x12\x1d\n\x19\x41TOM_CAMERA_STATE_CHANGED\x10\x19\x12!\n\x1d\x41TOM_FLASHLIGHT_STATE_CHANGED\x10\x1a\x12"\n\x1e\x41TOM_UID_PROCESS_STATE_CHANGED\x10\x1b\x12)\n%ATOM_PROCESS_LIFE_CYCLE_STATE_CHANGED\x10\x1c\x12\x1d\n\x19\x41TOM_SCREEN_STATE_CHANGED\x10\x1d\x12\x1e\n\x1a\x41TOM_BATTERY_LEVEL_CHANGED\x10\x1e\x12\x1f\n\x1b\x41TOM_CHARGING_STATE_CHANGED\x10\x1f\x12\x1e\n\x1a\x41TOM_PLUGGED_STATE_CHANGED\x10 \x12"\n\x1e\x41TOM_INTERACTIVE_STATE_CHANGED\x10!\x12\x1d\n\x19\x41TOM_TOUCH_EVENT_REPORTED\x10"\x12\x1e\n\x1a\x41TOM_WAKEUP_ALARM_OCCURRED\x10#\x12\x1f\n\x1b\x41TOM_KERNEL_WAKEUP_REPORTED\x10$\x12 \n\x1c\x41TOM_WIFI_LOCK_STATE_CHANGED\x10%\x12%\n!ATOM_WIFI_SIGNAL_STRENGTH_CHANGED\x10&\x12 \n\x1c\x41TOM_WIFI_SCAN_STATE_CHANGED\x10\'\x12&\n"ATOM_PHONE_SIGNAL_STRENGTH_CHANGED\x10(\x12\x18\n\x14\x41TOM_SETTING_CHANGED\x10)\x12*\n&ATOM_ACTIVITY_FOREGROUND_STATE_CHANGED\x10*\x12\x1d\n\x19\x41TOM_ISOLATED_UID_CHANGED\x10+\x12\x1f\n\x1b\x41TOM_PACKET_WAKEUP_OCCURRED\x10,\x12 \n\x1c\x41TOM_WALL_CLOCK_TIME_SHIFTED\x10-\x12\x19\n\x15\x41TOM_ANOMALY_DETECTED\x10.\x12 \n\x1c\x41TOM_APP_BREADCRUMB_REPORTED\x10/\x12\x1b\n\x17\x41TOM_APP_START_OCCURRED\x10\x30\x12\x1b\n\x17\x41TOM_APP_START_CANCELED\x10\x31\x12\x1e\n\x1a\x41TOM_APP_START_FULLY_DRAWN\x10\x32\x12\x1a\n\x16\x41TOM_LMK_KILL_OCCURRED\x10\x33\x12)\n%ATOM_PICTURE_IN_PICTURE_STATE_CHANGED\x10\x34\x12*\n&ATOM_WIFI_MULTICAST_LOCK_STATE_CHANGED\x10\x35\x12\x1a\n\x16\x41TOM_LMK_STATE_CHANGED\x10\x36\x12(\n$ATOM_APP_START_MEMORY_STATE_CAPTURED\x10\x37\x12#\n\x1f\x41TOM_SHUTDOWN_SEQUENCE_REPORTED\x10\x38\x12\x1f\n\x1b\x41TOM_BOOT_SEQUENCE_REPORTED\x10\x39\x12\x17\n\x13\x41TOM_DAVEY_OCCURRED\x10:\x12\x1e\n\x1a\x41TOM_OVERLAY_STATE_CHANGED\x10;\x12)\n%ATOM_FOREGROUND_SERVICE_STATE_CHANGED\x10<\x12\x1b\n\x17\x41TOM_CALL_STATE_CHANGED\x10=\x12\x1f\n\x1b\x41TOM_KEYGUARD_STATE_CHANGED\x10>\x12\'\n#ATOM_KEYGUARD_BOUNCER_STATE_CHANGED\x10?\x12*\n&ATOM_KEYGUARD_BOUNCER_PASSWORD_ENTERED\x10@\x12\x11\n\rATOM_APP_DIED\x10\x41\x12\'\n#ATOM_RESOURCE_CONFIGURATION_CHANGED\x10\x42\x12(\n$ATOM_BLUETOOTH_ENABLED_STATE_CHANGED\x10\x43\x12+\n\'ATOM_BLUETOOTH_CONNECTION_STATE_CHANGED\x10\x44\x12#\n\x1f\x41TOM_GPS_SIGNAL_QUALITY_CHANGED\x10\x45\x12$\n ATOM_USB_CONNECTOR_STATE_CHANGED\x10\x46\x12#\n\x1f\x41TOM_SPEAKER_IMPEDANCE_REPORTED\x10G\x12\x18\n\x14\x41TOM_HARDWARE_FAILED\x10H\x12\x1f\n\x1b\x41TOM_PHYSICAL_DROP_DETECTED\x10I\x12\x1f\n\x1b\x41TOM_CHARGE_CYCLES_REPORTED\x10J\x12(\n$ATOM_MOBILE_CONNECTION_STATE_CHANGED\x10K\x12(\n$ATOM_MOBILE_RADIO_TECHNOLOGY_CHANGED\x10L\x12\x1c\n\x18\x41TOM_USB_DEVICE_ATTACHED\x10M\x12\x1b\n\x17\x41TOM_APP_CRASH_OCCURRED\x10N\x12\x15\n\x11\x41TOM_ANR_OCCURRED\x10O\x12\x15\n\x11\x41TOM_WTF_OCCURRED\x10P\x12\x19\n\x15\x41TOM_LOW_MEM_REPORTED\x10Q\x12\x15\n\x11\x41TOM_GENERIC_ATOM\x10R\x12\x1f\n\x1b\x41TOM_VIBRATOR_STATE_CHANGED\x10T\x12$\n ATOM_DEFERRED_JOB_STATS_REPORTED\x10U\x12\x1b\n\x17\x41TOM_THERMAL_THROTTLING\x10V\x12\x1b\n\x17\x41TOM_BIOMETRIC_ACQUIRED\x10W\x12 \n\x1c\x41TOM_BIOMETRIC_AUTHENTICATED\x10X\x12!\n\x1d\x41TOM_BIOMETRIC_ERROR_OCCURRED\x10Y\x12\x1a\n\x16\x41TOM_UI_EVENT_REPORTED\x10Z\x12 \n\x1c\x41TOM_BATTERY_HEALTH_SNAPSHOT\x10[\x12\x10\n\x0c\x41TOM_SLOW_IO\x10\\\x12 \n\x1c\x41TOM_BATTERY_CAUSED_SHUTDOWN\x10]\x12$\n ATOM_PHONE_SERVICE_STATE_CHANGED\x10^\x12\x1c\n\x18\x41TOM_PHONE_STATE_CHANGED\x10_\x12!\n\x1d\x41TOM_USER_RESTRICTION_CHANGED\x10`\x12\x1c\n\x18\x41TOM_SETTINGS_UI_CHANGED\x10\x61\x12#\n\x1f\x41TOM_CONNECTIVITY_STATE_CHANGED\x10\x62\x12\x1e\n\x1a\x41TOM_SERVICE_STATE_CHANGED\x10\x63\x12 \n\x1c\x41TOM_SERVICE_LAUNCH_REPORTED\x10\x64\x12"\n\x1e\x41TOM_FLAG_FLIP_UPDATE_OCCURRED\x10\x65\x12"\n\x1e\x41TOM_BINARY_PUSH_STATE_CHANGED\x10\x66\x12\x1c\n\x18\x41TOM_DEVICE_POLICY_EVENT\x10g\x12!\n\x1d\x41TOM_DOCS_UI_FILE_OP_CANCELED\x10h\x12\x30\n,ATOM_DOCS_UI_FILE_OP_COPY_MOVE_MODE_REPORTED\x10i\x12 \n\x1c\x41TOM_DOCS_UI_FILE_OP_FAILURE\x10j\x12!\n\x1d\x41TOM_DOCS_UI_PROVIDER_FILE_OP\x10k\x12.\n*ATOM_DOCS_UI_INVALID_SCOPED_ACCESS_REQUEST\x10l\x12 \n\x1c\x41TOM_DOCS_UI_LAUNCH_REPORTED\x10m\x12\x1d\n\x19\x41TOM_DOCS_UI_ROOT_VISITED\x10n\x12\x1b\n\x17\x41TOM_DOCS_UI_STARTUP_MS\x10o\x12%\n!ATOM_DOCS_UI_USER_ACTION_REPORTED\x10p\x12#\n\x1f\x41TOM_WIFI_ENABLED_STATE_CHANGED\x10q\x12#\n\x1f\x41TOM_WIFI_RUNNING_STATE_CHANGED\x10r\x12\x16\n\x12\x41TOM_APP_COMPACTED\x10s\x12#\n\x1f\x41TOM_NETWORK_DNS_EVENT_REPORTED\x10t\x12.\n*ATOM_DOCS_UI_PICKER_LAUNCHED_FROM_REPORTED\x10u\x12%\n!ATOM_DOCS_UI_PICK_RESULT_REPORTED\x10v\x12%\n!ATOM_DOCS_UI_SEARCH_MODE_REPORTED\x10w\x12%\n!ATOM_DOCS_UI_SEARCH_TYPE_REPORTED\x10x\x12\x19\n\x15\x41TOM_DATA_STALL_EVENT\x10y\x12$\n ATOM_RESCUE_PARTY_RESET_REPORTED\x10z\x12\x1f\n\x1b\x41TOM_SIGNED_CONFIG_REPORTED\x10{\x12\x1f\n\x1b\x41TOM_GNSS_NI_EVENT_REPORTED\x10|\x12.\n*ATOM_BLUETOOTH_LINK_LAYER_CONNECTION_EVENT\x10}\x12/\n+ATOM_BLUETOOTH_ACL_CONNECTION_STATE_CHANGED\x10~\x12/\n+ATOM_BLUETOOTH_SCO_CONNECTION_STATE_CHANGED\x10\x7f\x12\x18\n\x13\x41TOM_APP_DOWNGRADED\x10\x80\x01\x12(\n#ATOM_APP_OPTIMIZED_AFTER_DOWNGRADED\x10\x81\x01\x12#\n\x1e\x41TOM_LOW_STORAGE_STATE_CHANGED\x10\x82\x01\x12(\n#ATOM_GNSS_NFW_NOTIFICATION_REPORTED\x10\x83\x01\x12%\n ATOM_GNSS_CONFIGURATION_REPORTED\x10\x84\x01\x12*\n%ATOM_USB_PORT_OVERHEAT_EVENT_REPORTED\x10\x85\x01\x12\x1c\n\x17\x41TOM_NFC_ERROR_OCCURRED\x10\x86\x01\x12\x1b\n\x16\x41TOM_NFC_STATE_CHANGED\x10\x87\x01\x12\x1b\n\x16\x41TOM_NFC_BEAM_OCCURRED\x10\x88\x01\x12$\n\x1f\x41TOM_NFC_CARDEMULATION_OCCURRED\x10\x89\x01\x12\x1a\n\x15\x41TOM_NFC_TAG_OCCURRED\x10\x8a\x01\x12&\n!ATOM_NFC_HCE_TRANSACTION_OCCURRED\x10\x8b\x01\x12\x1a\n\x15\x41TOM_SE_STATE_CHANGED\x10\x8c\x01\x12\x1b\n\x16\x41TOM_SE_OMAPI_REPORTED\x10\x8d\x01\x12-\n(ATOM_BROADCAST_DISPATCH_LATENCY_REPORTED\x10\x8e\x01\x12\x33\n.ATOM_ATTENTION_MANAGER_SERVICE_RESULT_REPORTED\x10\x8f\x01\x12 \n\x1b\x41TOM_ADB_CONNECTION_CHANGED\x10\x90\x01\x12"\n\x1d\x41TOM_SPEECH_DSP_STAT_REPORTED\x10\x91\x01\x12"\n\x1d\x41TOM_USB_CONTAMINANT_REPORTED\x10\x92\x01\x12$\n\x1f\x41TOM_WATCHDOG_ROLLBACK_OCCURRED\x10\x93\x01\x12\x30\n+ATOM_BIOMETRIC_SYSTEM_HEALTH_ISSUE_DETECTED\x10\x94\x01\x12\x1b\n\x16\x41TOM_BUBBLE_UI_CHANGED\x10\x95\x01\x12*\n%ATOM_SCHEDULED_JOB_CONSTRAINT_CHANGED\x10\x96\x01\x12)\n$ATOM_BLUETOOTH_ACTIVE_DEVICE_CHANGED\x10\x97\x01\x12/\n*ATOM_BLUETOOTH_A2DP_PLAYBACK_STATE_CHANGED\x10\x98\x01\x12-\n(ATOM_BLUETOOTH_A2DP_CODEC_CONFIG_CHANGED\x10\x99\x01\x12\x31\n,ATOM_BLUETOOTH_A2DP_CODEC_CAPABILITY_CHANGED\x10\x9a\x01\x12\x30\n+ATOM_BLUETOOTH_A2DP_AUDIO_UNDERRUN_REPORTED\x10\x9b\x01\x12/\n*ATOM_BLUETOOTH_A2DP_AUDIO_OVERRUN_REPORTED\x10\x9c\x01\x12(\n#ATOM_BLUETOOTH_DEVICE_RSSI_REPORTED\x10\x9d\x01\x12:\n5ATOM_BLUETOOTH_DEVICE_FAILED_CONTACT_COUNTER_REPORTED\x10\x9e\x01\x12\x32\n-ATOM_BLUETOOTH_DEVICE_TX_POWER_LEVEL_REPORTED\x10\x9f\x01\x12(\n#ATOM_BLUETOOTH_HCI_TIMEOUT_REPORTED\x10\xa0\x01\x12+\n&ATOM_BLUETOOTH_QUALITY_REPORT_REPORTED\x10\xa1\x01\x12(\n#ATOM_BLUETOOTH_DEVICE_INFO_REPORTED\x10\xa2\x01\x12\x30\n+ATOM_BLUETOOTH_REMOTE_VERSION_INFO_REPORTED\x10\xa3\x01\x12*\n%ATOM_BLUETOOTH_SDP_ATTRIBUTE_REPORTED\x10\xa4\x01\x12&\n!ATOM_BLUETOOTH_BOND_STATE_CHANGED\x10\xa5\x01\x12\x32\n-ATOM_BLUETOOTH_CLASSIC_PAIRING_EVENT_REPORTED\x10\xa6\x01\x12.\n)ATOM_BLUETOOTH_SMP_PAIRING_EVENT_REPORTED\x10\xa7\x01\x12+\n&ATOM_SCREEN_TIMEOUT_EXTENSION_REPORTED\x10\xa8\x01\x12\x1c\n\x17\x41TOM_PROCESS_START_TIME\x10\xa9\x01\x12\x32\n-ATOM_PERMISSION_GRANT_REQUEST_RESULT_REPORTED\x10\xaa\x01\x12\x33\n.ATOM_BLUETOOTH_SOCKET_CONNECTION_STATE_CHANGED\x10\xab\x01\x12)\n$ATOM_DEVICE_IDENTIFIER_ACCESS_DENIED\x10\xac\x01\x12)\n$ATOM_BUBBLE_DEVELOPER_ERROR_REPORTED\x10\xad\x01\x12\'\n"ATOM_ASSIST_GESTURE_STAGE_REPORTED\x10\xae\x01\x12*\n%ATOM_ASSIST_GESTURE_FEEDBACK_REPORTED\x10\xaf\x01\x12*\n%ATOM_ASSIST_GESTURE_PROGRESS_REPORTED\x10\xb0\x01\x12"\n\x1d\x41TOM_TOUCH_GESTURE_CLASSIFIED\x10\xb1\x01\x12\x19\n\x14\x41TOM_HIDDEN_API_USED\x10\xb2\x01\x12\x1a\n\x15\x41TOM_STYLE_UI_CHANGED\x10\xb3\x01\x12\'\n"ATOM_PRIVACY_INDICATORS_INTERACTED\x10\xb4\x01\x12\x32\n-ATOM_APP_INSTALL_ON_EXTERNAL_STORAGE_REPORTED\x10\xb5\x01\x12 \n\x1b\x41TOM_NETWORK_STACK_REPORTED\x10\xb6\x01\x12$\n\x1f\x41TOM_APP_MOVED_STORAGE_REPORTED\x10\xb7\x01\x12\x1c\n\x17\x41TOM_BIOMETRIC_ENROLLED\x10\xb8\x01\x12)\n$ATOM_SYSTEM_SERVER_WATCHDOG_OCCURRED\x10\xb9\x01\x12\x1d\n\x18\x41TOM_TOMB_STONE_OCCURRED\x10\xba\x01\x12,\n\'ATOM_BLUETOOTH_CLASS_OF_DEVICE_REPORTED\x10\xbb\x01\x12%\n ATOM_INTELLIGENCE_EVENT_REPORTED\x10\xbc\x01\x12\x33\n.ATOM_THERMAL_THROTTLING_SEVERITY_STATE_CHANGED\x10\xbd\x01\x12&\n!ATOM_ROLE_REQUEST_RESULT_REPORTED\x10\xbe\x01\x12+\n&ATOM_MEDIAMETRICS_AUDIOPOLICY_REPORTED\x10\xbf\x01\x12+\n&ATOM_MEDIAMETRICS_AUDIORECORD_REPORTED\x10\xc0\x01\x12+\n&ATOM_MEDIAMETRICS_AUDIOTHREAD_REPORTED\x10\xc1\x01\x12*\n%ATOM_MEDIAMETRICS_AUDIOTRACK_REPORTED\x10\xc2\x01\x12%\n ATOM_MEDIAMETRICS_CODEC_REPORTED\x10\xc3\x01\x12,\n\'ATOM_MEDIAMETRICS_DRM_WIDEVINE_REPORTED\x10\xc4\x01\x12)\n$ATOM_MEDIAMETRICS_EXTRACTOR_REPORTED\x10\xc5\x01\x12(\n#ATOM_MEDIAMETRICS_MEDIADRM_REPORTED\x10\xc6\x01\x12(\n#ATOM_MEDIAMETRICS_NUPLAYER_REPORTED\x10\xc7\x01\x12(\n#ATOM_MEDIAMETRICS_RECORDER_REPORTED\x10\xc8\x01\x12*\n%ATOM_MEDIAMETRICS_DRMMANAGER_REPORTED\x10\xc9\x01\x12!\n\x1c\x41TOM_CAR_POWER_STATE_CHANGED\x10\xcb\x01\x12\x1a\n\x15\x41TOM_GARAGE_MODE_INFO\x10\xcc\x01\x12\x1c\n\x17\x41TOM_TEST_ATOM_REPORTED\x10\xcd\x01\x12\x32\n-ATOM_CONTENT_CAPTURE_CALLER_MISMATCH_REPORTED\x10\xce\x01\x12(\n#ATOM_CONTENT_CAPTURE_SERVICE_EVENTS\x10\xcf\x01\x12(\n#ATOM_CONTENT_CAPTURE_SESSION_EVENTS\x10\xd0\x01\x12!\n\x1c\x41TOM_CONTENT_CAPTURE_FLUSHED\x10\xd1\x01\x12-\n(ATOM_LOCATION_MANAGER_API_USAGE_REPORTED\x10\xd2\x01\x12\x35\n0ATOM_REVIEW_PERMISSIONS_FRAGMENT_RESULT_REPORTED\x10\xd3\x01\x12,\n\'ATOM_RUNTIME_PERMISSIONS_UPGRADE_RESULT\x10\xd4\x01\x12\x33\n.ATOM_GRANT_PERMISSIONS_ACTIVITY_BUTTON_ACTIONS\x10\xd5\x01\x12\x33\n.ATOM_LOCATION_ACCESS_CHECK_NOTIFICATION_ACTION\x10\xd6\x01\x12\x31\n,ATOM_APP_PERMISSION_FRAGMENT_ACTION_REPORTED\x10\xd7\x01\x12(\n#ATOM_APP_PERMISSION_FRAGMENT_VIEWED\x10\xd8\x01\x12)\n$ATOM_APP_PERMISSIONS_FRAGMENT_VIEWED\x10\xd9\x01\x12)\n$ATOM_PERMISSION_APPS_FRAGMENT_VIEWED\x10\xda\x01\x12\x1e\n\x19\x41TOM_TEXT_SELECTION_EVENT\x10\xdb\x01\x12\x1c\n\x17\x41TOM_TEXT_LINKIFY_EVENT\x10\xdc\x01\x12$\n\x1f\x41TOM_CONVERSATION_ACTIONS_EVENT\x10\xdd\x01\x12"\n\x1d\x41TOM_LANGUAGE_DETECTION_EVENT\x10\xde\x01\x12&\n!ATOM_EXCLUSION_RECT_STATE_CHANGED\x10\xdf\x01\x12(\n#ATOM_BACK_GESTURE_REPORTED_REPORTED\x10\xe0\x01\x12/\n*ATOM_UPDATE_ENGINE_UPDATE_ATTEMPT_REPORTED\x10\xe1\x01\x12\x32\n-ATOM_UPDATE_ENGINE_SUCCESSFUL_UPDATE_REPORTED\x10\xe2\x01\x12\x1d\n\x18\x41TOM_CAMERA_ACTION_EVENT\x10\xe3\x01\x12+\n&ATOM_APP_COMPATIBILITY_CHANGE_REPORTED\x10\xe4\x01\x12\x1b\n\x16\x41TOM_PERFETTO_UPLOADED\x10\xe5\x01\x12-\n(ATOM_VMS_CLIENT_CONNECTION_STATE_CHANGED\x10\xe6\x01\x12&\n!ATOM_MEDIA_PROVIDER_SCAN_OCCURRED\x10\xe9\x01\x12\x1f\n\x1a\x41TOM_MEDIA_CONTENT_DELETED\x10\xea\x01\x12-\n(ATOM_MEDIA_PROVIDER_PERMISSION_REQUESTED\x10\xeb\x01\x12\'\n"ATOM_MEDIA_PROVIDER_SCHEMA_CHANGED\x10\xec\x01\x12\x32\n-ATOM_MEDIA_PROVIDER_IDLE_MAINTENANCE_FINISHED\x10\xed\x01\x12)\n$ATOM_REBOOT_ESCROW_RECOVERY_REPORTED\x10\xee\x01\x12+\n&ATOM_BOOT_TIME_EVENT_DURATION_REPORTED\x10\xef\x01\x12/\n*ATOM_BOOT_TIME_EVENT_ELAPSED_TIME_REPORTED\x10\xf0\x01\x12+\n&ATOM_BOOT_TIME_EVENT_UTC_TIME_REPORTED\x10\xf1\x01\x12-\n(ATOM_BOOT_TIME_EVENT_ERROR_CODE_REPORTED\x10\xf2\x01\x12#\n\x1e\x41TOM_USERSPACE_REBOOT_REPORTED\x10\xf3\x01\x12\x1f\n\x1a\x41TOM_NOTIFICATION_REPORTED\x10\xf4\x01\x12%\n ATOM_NOTIFICATION_PANEL_REPORTED\x10\xf5\x01\x12\'\n"ATOM_NOTIFICATION_CHANNEL_MODIFIED\x10\xf6\x01\x12)\n$ATOM_INTEGRITY_CHECK_RESULT_REPORTED\x10\xf7\x01\x12 \n\x1b\x41TOM_INTEGRITY_RULES_PUSHED\x10\xf8\x01\x12\x1d\n\x18\x41TOM_CB_MESSAGE_REPORTED\x10\xf9\x01\x12\x1a\n\x15\x41TOM_CB_MESSAGE_ERROR\x10\xfa\x01\x12#\n\x1e\x41TOM_WIFI_HEALTH_STAT_REPORTED\x10\xfb\x01\x12$\n\x1f\x41TOM_WIFI_FAILURE_STAT_REPORTED\x10\xfc\x01\x12)\n$ATOM_WIFI_CONNECTION_RESULT_REPORTED\x10\xfd\x01\x12\x1c\n\x17\x41TOM_APP_FREEZE_CHANGED\x10\xfe\x01\x12!\n\x1c\x41TOM_SNAPSHOT_MERGE_REPORTED\x10\xff\x01\x12\x31\n,ATOM_FOREGROUND_SERVICE_APP_OP_SESSION_ENDED\x10\x80\x02\x12\x1f\n\x1a\x41TOM_DISPLAY_JANK_REPORTED\x10\x81\x02\x12$\n\x1f\x41TOM_APP_STANDBY_BUCKET_CHANGED\x10\x82\x02\x12\x1c\n\x17\x41TOM_SHARESHEET_STARTED\x10\x83\x02\x12\x1a\n\x15\x41TOM_RANKING_SELECTED\x10\x84\x02\x12"\n\x1d\x41TOM_TVSETTINGS_UI_INTERACTED\x10\x85\x02\x12\x1b\n\x16\x41TOM_LAUNCHER_SNAPSHOT\x10\x86\x02\x12\'\n"ATOM_PACKAGE_INSTALLER_V2_REPORTED\x10\x87\x02\x12)\n$ATOM_USER_LIFECYCLE_JOURNEY_REPORTED\x10\x88\x02\x12\'\n"ATOM_USER_LIFECYCLE_EVENT_OCCURRED\x10\x89\x02\x12)\n$ATOM_ACCESSIBILITY_SHORTCUT_REPORTED\x10\x8a\x02\x12(\n#ATOM_ACCESSIBILITY_SERVICE_REPORTED\x10\x8b\x02\x12(\n#ATOM_DOCS_UI_DRAG_AND_DROP_REPORTED\x10\x8c\x02\x12"\n\x1d\x41TOM_APP_USAGE_EVENT_OCCURRED\x10\x8d\x02\x12*\n%ATOM_AUTO_REVOKE_NOTIFICATION_CLICKED\x10\x8e\x02\x12)\n$ATOM_AUTO_REVOKE_FRAGMENT_APP_VIEWED\x10\x8f\x02\x12&\n!ATOM_AUTO_REVOKED_APP_INTERACTION\x10\x90\x02\x12;\n6ATOM_APP_PERMISSION_GROUPS_FRAGMENT_AUTO_REVOKE_ACTION\x10\x91\x02\x12"\n\x1d\x41TOM_EVS_USAGE_STATS_REPORTED\x10\x92\x02\x12)\n$ATOM_AUDIO_POWER_USAGE_DATA_REPORTED\x10\x93\x02\x12 \n\x1b\x41TOM_TV_TUNER_STATE_CHANGED\x10\x94\x02\x12(\n#ATOM_MEDIAOUTPUT_OP_SWITCH_REPORTED\x10\x95\x02\x12\x1d\n\x18\x41TOM_CB_MESSAGE_FILTERED\x10\x96\x02\x12\x1d\n\x18\x41TOM_TV_TUNER_DVR_STATUS\x10\x97\x02\x12$\n\x1f\x41TOM_TV_CAS_SESSION_OPEN_STATUS\x10\x98\x02\x12\'\n"ATOM_ASSISTANT_INVOCATION_REPORTED\x10\x99\x02\x12\x1f\n\x1a\x41TOM_DISPLAY_WAKE_REPORTED\x10\x9a\x02\x12\x33\n.ATOM_CAR_USER_HAL_MODIFY_USER_REQUEST_REPORTED\x10\x9b\x02\x12\x34\n/ATOM_CAR_USER_HAL_MODIFY_USER_RESPONSE_REPORTED\x10\x9c\x02\x12\x34\n/ATOM_CAR_USER_HAL_POST_SWITCH_RESPONSE_REPORTED\x10\x9d\x02\x12\x39\n4ATOM_CAR_USER_HAL_INITIAL_USER_INFO_REQUEST_REPORTED\x10\x9e\x02\x12:\n5ATOM_CAR_USER_HAL_INITIAL_USER_INFO_RESPONSE_REPORTED\x10\x9f\x02\x12\x38\n3ATOM_CAR_USER_HAL_USER_ASSOCIATION_REQUEST_REPORTED\x10\xa0\x02\x12=\n8ATOM_CAR_USER_HAL_SET_USER_ASSOCIATION_RESPONSE_REPORTED\x10\xa1\x02\x12*\n%ATOM_NETWORK_IP_PROVISIONING_REPORTED\x10\xa2\x02\x12%\n ATOM_NETWORK_DHCP_RENEW_REPORTED\x10\xa3\x02\x12%\n ATOM_NETWORK_VALIDATION_REPORTED\x10\xa4\x02\x12&\n!ATOM_NETWORK_STACK_QUIRK_REPORTED\x10\xa5\x02\x12\x36\n1ATOM_MEDIAMETRICS_AUDIORECORDDEVICEUSAGE_REPORTED\x10\xa6\x02\x12\x36\n1ATOM_MEDIAMETRICS_AUDIOTHREADDEVICEUSAGE_REPORTED\x10\xa7\x02\x12\x35\n0ATOM_MEDIAMETRICS_AUDIOTRACKDEVICEUSAGE_REPORTED\x10\xa8\x02\x12\x35\n0ATOM_MEDIAMETRICS_AUDIODEVICECONNECTION_REPORTED\x10\xa9\x02\x12\x18\n\x13\x41TOM_BLOB_COMMITTED\x10\xaa\x02\x12\x15\n\x10\x41TOM_BLOB_LEASED\x10\xab\x02\x12\x15\n\x10\x41TOM_BLOB_OPENED\x10\xac\x02\x12+\n&ATOM_CONTACTS_PROVIDER_STATUS_REPORTED\x10\xad\x02\x12%\n ATOM_KEYSTORE_KEY_EVENT_REPORTED\x10\xae\x02\x12$\n\x1f\x41TOM_NETWORK_TETHERING_REPORTED\x10\xaf\x02\x12\x1c\n\x17\x41TOM_IME_TOUCH_REPORTED\x10\xb0\x02\x12,\n\'ATOM_UI_INTERACTION_FRAME_INFO_REPORTED\x10\xb1\x02\x12$\n\x1f\x41TOM_UI_ACTION_LATENCY_REPORTED\x10\xb2\x02\x12"\n\x1d\x41TOM_WIFI_DISCONNECT_REPORTED\x10\xb3\x02\x12\'\n"ATOM_WIFI_CONNECTION_STATE_CHANGED\x10\xb4\x02\x12(\n#ATOM_HDMI_CEC_ACTIVE_SOURCE_CHANGED\x10\xb5\x02\x12#\n\x1e\x41TOM_HDMI_CEC_MESSAGE_REPORTED\x10\xb6\x02\x12\x17\n\x12\x41TOM_AIRPLANE_MODE\x10\xb7\x02\x12\x17\n\x12\x41TOM_MODEM_RESTART\x10\xb8\x02\x12&\n!ATOM_CARRIER_ID_MISMATCH_REPORTED\x10\xb9\x02\x12"\n\x1d\x41TOM_CARRIER_ID_TABLE_UPDATED\x10\xba\x02\x12&\n!ATOM_DATA_STALL_RECOVERY_REPORTED\x10\xbb\x02\x12+\n&ATOM_MEDIAMETRICS_MEDIAPARSER_REPORTED\x10\xbc\x02\x12 \n\x1b\x41TOM_TLS_HANDSHAKE_REPORTED\x10\xbd\x02\x12,\n\'ATOM_TEXT_CLASSIFIER_API_USAGE_REPORTED\x10\xbe\x02\x12*\n%ATOM_CAR_WATCHDOG_KILL_STATS_REPORTED\x10\xbf\x02\x12(\n#ATOM_MEDIAMETRICS_PLAYBACK_REPORTED\x10\xc0\x02\x12$\n\x1f\x41TOM_MEDIA_NETWORK_INFO_CHANGED\x10\xc1\x02\x12&\n!ATOM_MEDIA_PLAYBACK_STATE_CHANGED\x10\xc2\x02\x12\'\n"ATOM_MEDIA_PLAYBACK_ERROR_REPORTED\x10\xc3\x02\x12&\n!ATOM_MEDIA_PLAYBACK_TRACK_CHANGED\x10\xc4\x02\x12\x1c\n\x17\x41TOM_WIFI_SCAN_REPORTED\x10\xc5\x02\x12 \n\x1b\x41TOM_WIFI_PNO_SCAN_REPORTED\x10\xc6\x02\x12\x1a\n\x15\x41TOM_TIF_TUNE_CHANGED\x10\xc7\x02\x12\x1e\n\x19\x41TOM_AUTO_ROTATE_REPORTED\x10\xc8\x02\x12\x1a\n\x15\x41TOM_PERFETTO_TRIGGER\x10\xc9\x02\x12\x1a\n\x15\x41TOM_TRANSCODING_DATA\x10\xca\x02\x12)\n$ATOM_IMS_SERVICE_ENTITLEMENT_UPDATED\x10\xcb\x02\x12\x18\n\x13\x41TOM_DEVICE_ROTATED\x10\xcd\x02\x12(\n#ATOM_SIM_SPECIFIC_SETTINGS_RESTORED\x10\xce\x02\x12+\n&ATOM_TEXT_CLASSIFIER_DOWNLOAD_REPORTED\x10\xcf\x02\x12\x1b\n\x16\x41TOM_PIN_STORAGE_EVENT\x10\xd0\x02\x12\x1c\n\x17\x41TOM_FACE_DOWN_REPORTED\x10\xd1\x02\x12-\n(ATOM_BLUETOOTH_HAL_CRASH_REASON_REPORTED\x10\xd2\x02\x12,\n\'ATOM_REBOOT_ESCROW_PREPARATION_REPORTED\x10\xd3\x02\x12-\n(ATOM_REBOOT_ESCROW_LSKF_CAPTURE_REPORTED\x10\xd4\x02\x12\'\n"ATOM_REBOOT_ESCROW_REBOOT_REPORTED\x10\xd5\x02\x12!\n\x1c\x41TOM_BINDER_LATENCY_REPORTED\x10\xd6\x02\x12,\n\'ATOM_MEDIAMETRICS_AAUDIOSTREAM_REPORTED\x10\xd7\x02\x12)\n$ATOM_MEDIA_TRANSCODING_SESSION_ENDED\x10\xd8\x02\x12&\n!ATOM_MAGNIFICATION_USAGE_REPORTED\x10\xd9\x02\x12\x31\n,ATOM_MAGNIFICATION_MODE_WITH_IME_ON_REPORTED\x10\xda\x02\x12(\n#ATOM_APP_SEARCH_CALL_STATS_REPORTED\x10\xdb\x02\x12\x30\n+ATOM_APP_SEARCH_PUT_DOCUMENT_STATS_REPORTED\x10\xdc\x02\x12 \n\x1b\x41TOM_DEVICE_CONTROL_CHANGED\x10\xdd\x02\x12\x1e\n\x19\x41TOM_DEVICE_STATE_CHANGED\x10\xde\x02\x12 \n\x1b\x41TOM_INPUTDEVICE_REGISTERED\x10\xdf\x02\x12"\n\x1d\x41TOM_SMARTSPACE_CARD_REPORTED\x10\xe0\x02\x12*\n%ATOM_AUTH_PROMPT_AUTHENTICATE_INVOKED\x10\xe1\x02\x12/\n*ATOM_AUTH_MANAGER_CAN_AUTHENTICATE_INVOKED\x10\xe2\x02\x12$\n\x1f\x41TOM_AUTH_ENROLL_ACTION_INVOKED\x10\xe3\x02\x12"\n\x1d\x41TOM_AUTH_DEPRECATED_API_USED\x10\xe4\x02\x12$\n\x1f\x41TOM_UNATTENDED_REBOOT_OCCURRED\x10\xe5\x02\x12\'\n"ATOM_LONG_REBOOT_BLOCKING_REPORTED\x10\xe6\x02\x12\x33\n.ATOM_LOCATION_TIME_ZONE_PROVIDER_STATE_CHANGED\x10\xe7\x02\x12 \n\x1b\x41TOM_FDTRACK_EVENT_OCCURRED\x10\xec\x02\x12(\n#ATOM_TIMEOUT_AUTO_EXTENDED_REPORTED\x10\xed\x02\x12\x1f\n\x1a\x41TOM_ALARM_BATCH_DELIVERED\x10\xef\x02\x12\x19\n\x14\x41TOM_ALARM_SCHEDULED\x10\xf0\x02\x12\x30\n+ATOM_CAR_WATCHDOG_IO_OVERUSE_STATS_REPORTED\x10\xf1\x02\x12.\n)ATOM_USER_LEVEL_HIBERNATION_STATE_CHANGED\x10\xf2\x02\x12.\n)ATOM_APP_SEARCH_INITIALIZE_STATS_REPORTED\x10\xf3\x02\x12)\n$ATOM_APP_SEARCH_QUERY_STATS_REPORTED\x10\xf4\x02\x12\x1a\n\x15\x41TOM_APP_PROCESS_DIED\x10\xf5\x02\x12\x32\n-ATOM_NETWORK_IP_REACHABILITY_MONITOR_REPORTED\x10\xf6\x02\x12#\n\x1e\x41TOM_SLOW_INPUT_EVENT_REPORTED\x10\xf7\x02\x12)\n$ATOM_ANR_OCCURRED_PROCESSING_STARTED\x10\xf8\x02\x12*\n%ATOM_APP_SEARCH_REMOVE_STATS_REPORTED\x10\xf9\x02\x12\x1e\n\x19\x41TOM_MEDIA_CODEC_REPORTED\x10\xfa\x02\x12/\n*ATOM_PERMISSION_USAGE_FRAGMENT_INTERACTION\x10\xfb\x02\x12(\n#ATOM_PERMISSION_DETAILS_INTERACTION\x10\xfc\x02\x12+\n&ATOM_PRIVACY_SENSOR_TOGGLE_INTERACTION\x10\xfd\x02\x12+\n&ATOM_PRIVACY_TOGGLE_DIALOG_INTERACTION\x10\xfe\x02\x12,\n\'ATOM_APP_SEARCH_OPTIMIZE_STATS_REPORTED\x10\xff\x02\x12.\n)ATOM_NON_A11Y_TOOL_SERVICE_WARNING_REPORT\x10\x80\x03\x12.\n)ATOM_APP_SEARCH_SET_SCHEMA_STATS_REPORTED\x10\x81\x03\x12"\n\x1d\x41TOM_APP_COMPAT_STATE_CHANGED\x10\x82\x03\x12\x33\n.ATOM_SIZE_COMPAT_RESTART_BUTTON_EVENT_REPORTED\x10\x83\x03\x12 \n\x1b\x41TOM_SPLITSCREEN_UI_CHANGED\x10\x84\x03\x12(\n#ATOM_NETWORK_DNS_HANDSHAKE_REPORTED\x10\x85\x03\x12%\n ATOM_BLUETOOTH_CODE_PATH_COUNTER\x10\x86\x03\x12.\n)ATOM_BLUETOOTH_LE_BATCH_SCAN_REPORT_DELAY\x10\x88\x03\x12\x30\n+ATOM_ACCESSIBILITY_FLOATING_MENU_UI_CHANGED\x10\x89\x03\x12.\n)ATOM_NEURALNETWORKS_COMPILATION_COMPLETED\x10\x8a\x03\x12,\n\'ATOM_NEURALNETWORKS_EXECUTION_COMPLETED\x10\x8b\x03\x12+\n&ATOM_NEURALNETWORKS_COMPILATION_FAILED\x10\x8c\x03\x12)\n$ATOM_NEURALNETWORKS_EXECUTION_FAILED\x10\x8d\x03\x12\x1c\n\x17\x41TOM_CONTEXT_HUB_BOOTED\x10\x8e\x03\x12\x1f\n\x1a\x41TOM_CONTEXT_HUB_RESTARTED\x10\x8f\x03\x12\x36\n1ATOM_CONTEXT_HUB_LOADED_NANOAPP_SNAPSHOT_REPORTED\x10\x90\x03\x12\'\n"ATOM_CHRE_CODE_DOWNLOAD_TRANSACTED\x10\x91\x03\x12\x1c\n\x17\x41TOM_UWB_SESSION_INITED\x10\x92\x03\x12\x1c\n\x17\x41TOM_UWB_SESSION_CLOSED\x10\x93\x03\x12$\n\x1f\x41TOM_UWB_FIRST_RANGING_RECEIVED\x10\x94\x03\x12*\n%ATOM_UWB_RANGING_MEASUREMENT_RECEIVED\x10\x95\x03\x12\x31\n,ATOM_TEXT_CLASSIFIER_DOWNLOAD_WORK_SCHEDULED\x10\x96\x03\x12\x31\n,ATOM_TEXT_CLASSIFIER_DOWNLOAD_WORK_COMPLETED\x10\x97\x03\x12\x1b\n\x16\x41TOM_CLIPBOARD_CLEARED\x10\x98\x03\x12\x1f\n\x1a\x41TOM_VM_CREATION_REQUESTED\x10\x99\x03\x12*\n%ATOM_NEARBY_DEVICE_SCAN_STATE_CHANGED\x10\x9a\x03\x12.\n)ATOM_CAMERA_COMPAT_CONTROL_EVENT_REPORTED\x10\x9b\x03\x12%\n ATOM_APPLICATION_LOCALES_CHANGED\x10\x9c\x03\x12\x30\n+ATOM_MEDIAMETRICS_AUDIOTRACKSTATUS_REPORTED\x10\x9d\x03\x12&\n!ATOM_FOLD_STATE_DURATION_REPORTED\x10\x9e\x03\x12>\n9ATOM_LOCATION_TIME_ZONE_PROVIDER_CONTROLLER_STATE_CHANGED\x10\x9f\x03\x12#\n\x1e\x41TOM_DISPLAY_HBM_STATE_CHANGED\x10\xa0\x03\x12(\n#ATOM_DISPLAY_HBM_BRIGHTNESS_CHANGED\x10\xa1\x03\x12,\n\'ATOM_PERSISTENT_URI_PERMISSIONS_FLUSHED\x10\xa2\x03\x12\x35\n0ATOM_EARLY_BOOT_COMP_OS_ARTIFACTS_CHECK_REPORTED\x10\xa3\x03\x12 \n\x1b\x41TOM_VBMETA_DIGEST_REPORTED\x10\xa4\x03\x12\x1c\n\x17\x41TOM_APEX_INFO_GATHERED\x10\xa5\x03\x12\x1b\n\x16\x41TOM_PVM_INFO_GATHERED\x10\xa6\x03\x12%\n ATOM_WEAR_SETTINGS_UI_INTERACTED\x10\xa7\x03\x12&\n!ATOM_TRACING_SERVICE_REPORT_EVENT\x10\xa8\x03\x12\x31\n,ATOM_MEDIAMETRICS_AUDIORECORDSTATUS_REPORTED\x10\xa9\x03\x12\x1a\n\x15\x41TOM_LAUNCHER_LATENCY\x10\xaa\x03\x12\x1f\n\x1a\x41TOM_DROPBOX_ENTRY_DROPPED\x10\xab\x03\x12&\n!ATOM_WIFI_P2P_CONNECTION_REPORTED\x10\xac\x03\x12\x1c\n\x17\x41TOM_GAME_STATE_CHANGED\x10\xad\x03\x12+\n&ATOM_HOTWORD_DETECTOR_CREATE_REQUESTED\x10\xae\x03\x12\x38\n3ATOM_HOTWORD_DETECTION_SERVICE_INIT_RESULT_REPORTED\x10\xaf\x03\x12-\n(ATOM_HOTWORD_DETECTION_SERVICE_RESTARTED\x10\xb0\x03\x12.\n)ATOM_HOTWORD_DETECTOR_KEYPHRASE_TRIGGERED\x10\xb1\x03\x12!\n\x1c\x41TOM_HOTWORD_DETECTOR_EVENTS\x10\xb2\x03\x12 \n\x1b\x41TOM_AD_SERVICES_API_CALLED\x10\xb3\x03\x12\x31\n,ATOM_AD_SERVICES_MESUREMENT_REPORTS_UPLOADED\x10\xb4\x03\x12>\n9ATOM_BOOT_COMPLETED_BROADCAST_COMPLETION_LATENCY_REPORTED\x10\xb5\x03\x12\x30\n+ATOM_CONTACTS_INDEXER_UPDATE_STATS_REPORTED\x10\xb8\x03\x12*\n%ATOM_APP_BACKGROUND_RESTRICTIONS_INFO\x10\xb9\x03\x12/\n*ATOM_MMS_SMS_PROVIDER_GET_THREAD_ID_FAILED\x10\xba\x03\x12\x33\n.ATOM_MMS_SMS_DATABASE_HELPER_ON_UPGRADE_FAILED\x10\xbb\x03\x12\x35\n0ATOM_PERMISSION_REMINDER_NOTIFICATION_INTERACTED\x10\xbc\x03\x12\x30\n+ATOM_RECENT_PERMISSION_DECISIONS_INTERACTED\x10\xbd\x03\x12%\n ATOM_GNSS_PSDS_DOWNLOAD_REPORTED\x10\xbe\x03\x12.\n)ATOM_LE_AUDIO_CONNECTION_SESSION_REPORTED\x10\xbf\x03\x12-\n(ATOM_LE_AUDIO_BROADCAST_SESSION_REPORTED\x10\xc0\x03\x12!\n\x1c\x41TOM_DREAM_UI_EVENT_REPORTED\x10\xc1\x03\x12%\n ATOM_TASK_MANAGER_EVENT_REPORTED\x10\xc2\x03\x12 \n\x1b\x41TOM_CDM_ASSOCIATION_ACTION\x10\xc3\x03\x12\x46\nAATOM_MAGNIFICATION_TRIPLE_TAP_AND_HOLD_ACTIVATED_SESSION_REPORTED\x10\xc4\x03\x12\x46\nAATOM_MAGNIFICATION_FOLLOW_TYPING_FOCUS_ACTIVATED_SESSION_REPORTED\x10\xc5\x03\x12\x34\n/ATOM_ACCESSIBILITY_TEXT_READING_OPTIONS_CHANGED\x10\xc6\x03\x12+\n&ATOM_WIFI_SETUP_FAILURE_CRASH_REPORTED\x10\xc7\x03\x12#\n\x1e\x41TOM_UWB_DEVICE_ERROR_REPORTED\x10\xc8\x03\x12(\n#ATOM_ISOLATED_COMPILATION_SCHEDULED\x10\xc9\x03\x12$\n\x1f\x41TOM_ISOLATED_COMPILATION_ENDED\x10\xca\x03\x12\x36\n1ATOM_ONS_OPPORTUNISTIC_ESIM_PROVISIONING_COMPLETE\x10\xcb\x03\x12-\n(ATOM_SYSTEM_SERVER_PRE_WATCHDOG_OCCURRED\x10\xcc\x03\x12$\n\x1f\x41TOM_TELEPHONY_ANOMALY_DETECTED\x10\xcd\x03\x12$\n\x1f\x41TOM_LETTERBOX_POSITION_CHANGED\x10\xce\x03\x12)\n$ATOM_REMOTE_KEY_PROVISIONING_ATTEMPT\x10\xcf\x03\x12.\n)ATOM_REMOTE_KEY_PROVISIONING_NETWORK_INFO\x10\xd0\x03\x12(\n#ATOM_REMOTE_KEY_PROVISIONING_TIMING\x10\xd1\x03\x12+\n&ATOM_MEDIAOUTPUT_OP_INTERACTION_REPORT\x10\xd2\x03\x12!\n\x1c\x41TOM_SYNC_EXEMPTION_OCCURRED\x10\xd4\x03\x12.\n)ATOM_AUTOFILL_PRESENTATION_EVENT_REPORTED\x10\xd5\x03\x12\x1c\n\x17\x41TOM_DOCK_STATE_CHANGED\x10\xd6\x03\x12\'\n"ATOM_SAFETY_SOURCE_STATE_COLLECTED\x10\xd7\x03\x12-\n(ATOM_SAFETY_CENTER_SYSTEM_EVENT_REPORTED\x10\xd8\x03\x12,\n\'ATOM_SAFETY_CENTER_INTERACTION_REPORTED\x10\xd9\x03\x12+\n&ATOM_SETTINGS_PROVIDER_SETTING_CHANGED\x10\xda\x03\x12+\n&ATOM_BROADCAST_DELIVERY_EVENT_REPORTED\x10\xdb\x03\x12(\n#ATOM_SERVICE_REQUEST_EVENT_REPORTED\x10\xdc\x03\x12-\n(ATOM_PROVIDER_ACQUISITION_EVENT_REPORTED\x10\xdd\x03\x12(\n#ATOM_BLUETOOTH_DEVICE_NAME_REPORTED\x10\xde\x03\x12\x1b\n\x16\x41TOM_CB_CONFIG_UPDATED\x10\xdf\x03\x12"\n\x1d\x41TOM_CB_MODULE_ERROR_REPORTED\x10\xe0\x03\x12$\n\x1f\x41TOM_CB_SERVICE_FEATURE_CHANGED\x10\xe1\x03\x12%\n ATOM_CB_RECEIVER_FEATURE_CHANGED\x10\xe2\x03\x12)\n$ATOM_JSSCRIPTENGINE_LATENCY_REPORTED\x10\xe3\x03\x12\x31\n,ATOM_PRIVACY_SIGNAL_NOTIFICATION_INTERACTION\x10\xe4\x03\x12/\n*ATOM_PRIVACY_SIGNAL_ISSUE_CARD_INTERACTION\x10\xe5\x03\x12%\n ATOM_PRIVACY_SIGNALS_JOB_FAILURE\x10\xe6\x03\x12\x1c\n\x17\x41TOM_VIBRATION_REPORTED\x10\xe7\x03\x12\x1b\n\x16\x41TOM_UWB_RANGING_START\x10\xe9\x03\x12\x39\n4ATOM_MOBILE_DATA_DOWNLOAD_FILE_GROUP_STATUS_REPORTED\x10\xea\x03\x12\x1a\n\x15\x41TOM_APP_COMPACTED_V2\x10\xeb\x03\x12-\n(ATOM_AD_SERVICES_SETTINGS_USAGE_REPORTED\x10\xed\x03\x12$\n\x1f\x41TOM_DISPLAY_BRIGHTNESS_CHANGED\x10\xee\x03\x12!\n\x1c\x41TOM_ACTIVITY_ACTION_BLOCKED\x10\xef\x03\x12+\n&ATOM_BACKGROUND_FETCH_PROCESS_REPORTED\x10\xf0\x03\x12\x31\n,ATOM_UPDATE_CUSTOM_AUDIENCE_PROCESS_REPORTED\x10\xf1\x03\x12)\n$ATOM_RUN_AD_BIDDING_PROCESS_REPORTED\x10\xf2\x03\x12)\n$ATOM_RUN_AD_SCORING_PROCESS_REPORTED\x10\xf3\x03\x12+\n&ATOM_RUN_AD_SELECTION_PROCESS_REPORTED\x10\xf4\x03\x12\x30\n+ATOM_RUN_AD_BIDDING_PER_CA_PROCESS_REPORTED\x10\xf5\x03\x12\x37\n2ATOM_MOBILE_DATA_DOWNLOAD_DOWNLOAD_RESULT_REPORTED\x10\xf6\x03\x12@\n;ATOM_MOBILE_DATA_DOWNLOAD_FILE_GROUP_STORAGE_STATS_REPORTED\x10\xf7\x03\x12-\n(ATOM_NETWORK_DNS_SERVER_SUPPORT_REPORTED\x10\xf8\x03\x12\x13\n\x0e\x41TOM_VM_BOOTED\x10\xf9\x03\x12\x13\n\x0e\x41TOM_VM_EXITED\x10\xfa\x03\x12+\n&ATOM_AMBIENT_BRIGHTNESS_STATS_REPORTED\x10\xfb\x03\x12\x37\n2ATOM_MEDIAMETRICS_SPATIALIZERCAPABILITIES_REPORTED\x10\xfc\x03\x12\x38\n3ATOM_MEDIAMETRICS_SPATIALIZERDEVICEENABLED_REPORTED\x10\xfd\x03\x12\x38\n3ATOM_MEDIAMETRICS_HEADTRACKERDEVICEENABLED_REPORTED\x10\xfe\x03\x12:\n5ATOM_MEDIAMETRICS_HEADTRACKERDEVICESUPPORTED_REPORTED\x10\xff\x03\x12/\n*ATOM_AD_SERVICES_MEASUREMENT_REGISTRATIONS\x10\x80\x04\x12#\n\x1e\x41TOM_HEARING_AID_INFO_REPORTED\x10\x81\x04\x12,\n\'ATOM_DEVICE_WIDE_JOB_CONSTRAINT_CHANGED\x10\x82\x04\x12\x1e\n\x19\x41TOM_AMBIENT_MODE_CHANGED\x10\x83\x04\x12\x1e\n\x19\x41TOM_ANR_LATENCY_REPORTED\x10\x84\x04\x12\x1b\n\x16\x41TOM_RESOURCE_API_INFO\x10\x85\x04\x12(\n#ATOM_SYSTEM_DEFAULT_NETWORK_CHANGED\x10\x86\x04\x12/\n*ATOM_IWLAN_SETUP_DATA_CALL_RESULT_REPORTED\x10\x87\x04\x12\x30\n+ATOM_IWLAN_PDN_DISCONNECTED_REASON_REPORTED\x10\x88\x04\x12(\n#ATOM_AIRPLANE_MODE_SESSION_REPORTED\x10\x89\x04\x12 \n\x1b\x41TOM_VM_CPU_STATUS_REPORTED\x10\x8a\x04\x12 \n\x1b\x41TOM_VM_MEM_STATUS_REPORTED\x10\x8b\x04\x12/\n*ATOM_PACKAGE_INSTALLATION_SESSION_REPORTED\x10\x8c\x04\x12&\n!ATOM_DEFAULT_NETWORK_REMATCH_INFO\x10\x8d\x04\x12\'\n"ATOM_NETWORK_SELECTION_PERFORMANCE\x10\x8e\x04\x12\x1e\n\x19\x41TOM_NETWORK_NSD_REPORTED\x10\x8f\x04\x12\x31\n,ATOM_BLUETOOTH_DISCONNECTION_REASON_REPORTED\x10\x91\x04\x12+\n&ATOM_BLUETOOTH_LOCAL_VERSIONS_REPORTED\x10\x92\x04\x12\x36\n1ATOM_BLUETOOTH_REMOTE_SUPPORTED_FEATURES_REPORTED\x10\x93\x04\x12\x35\n0ATOM_BLUETOOTH_LOCAL_SUPPORTED_FEATURES_REPORTED\x10\x94\x04\x12!\n\x1c\x41TOM_BLUETOOTH_GATT_APP_INFO\x10\x95\x04\x12*\n%ATOM_BRIGHTNESS_CONFIGURATION_UPDATED\x10\x96\x04\x12)\n$ATOM_AD_SERVICES_GET_TOPICS_REPORTED\x10\x97\x04\x12?\n:ATOM_AD_SERVICES_EPOCH_COMPUTATION_GET_TOP_TOPICS_REPORTED\x10\x98\x04\x12;\n6ATOM_AD_SERVICES_EPOCH_COMPUTATION_CLASSIFIER_REPORTED\x10\x99\x04\x12-\n(ATOM_WEAR_MEDIA_OUTPUT_SWITCHER_LAUNCHED\x10\x9a\x04\x12-\n(ATOM_WEAR_MEDIA_OUTPUT_SWITCHER_FINISHED\x10\x9b\x04\x12\x38\n3ATOM_WEAR_MEDIA_OUTPUT_SWITCHER_CONNECTION_REPORTED\x10\x9c\x04\x12:\n5ATOM_WEAR_MEDIA_OUTPUT_SWITCHER_DEVICE_SCAN_TRIGGERED\x10\x9d\x04\x12>\n9ATOM_WEAR_MEDIA_OUTPUT_SWITCHER_FIRST_DEVICE_SCAN_LATENCY\x10\x9e\x04\x12;\n6ATOM_WEAR_MEDIA_OUTPUT_SWITCHER_CONNECT_DEVICE_LATENCY\x10\x9f\x04\x12+\n&ATOM_PACKAGE_MANAGER_SNAPSHOT_REPORTED\x10\xa0\x04\x12:\n5ATOM_PACKAGE_MANAGER_APPS_FILTER_CACHE_BUILD_REPORTED\x10\xa1\x04\x12;\n6ATOM_PACKAGE_MANAGER_APPS_FILTER_CACHE_UPDATE_REPORTED\x10\xa2\x04\x12#\n\x1e\x41TOM_LAUNCHER_IMPRESSION_EVENT\x10\xa3\x04\x12=\n8ATOM_WEAR_MEDIA_OUTPUT_SWITCHER_ALL_DEVICES_SCAN_LATENCY\x10\xa5\x04\x12\x1e\n\x19\x41TOM_WS_WATCH_FACE_EDITED\x10\xa7\x04\x12\x30\n+ATOM_WS_WATCH_FACE_FAVORITE_ACTION_REPORTED\x10\xa8\x04\x12+\n&ATOM_WS_WATCH_FACE_SET_ACTION_REPORTED\x10\xa9\x04\x12)\n$ATOM_PACKAGE_UNINSTALLATION_REPORTED\x10\xaa\x04\x12\x1b\n\x16\x41TOM_GAME_MODE_CHANGED\x10\xab\x04\x12)\n$ATOM_GAME_MODE_CONFIGURATION_CHANGED\x10\xac\x04\x12$\n\x1f\x41TOM_BEDTIME_MODE_STATE_CHANGED\x10\xad\x04\x12%\n ATOM_NETWORK_SLICE_SESSION_ENDED\x10\xae\x04\x12\x31\n,ATOM_NETWORK_SLICE_DAILY_DATA_USAGE_REPORTED\x10\xaf\x04\x12\x1f\n\x1a\x41TOM_NFC_TAG_TYPE_OCCURRED\x10\xb0\x04\x12#\n\x1e\x41TOM_NFC_AID_CONFLICT_OCCURRED\x10\xb1\x04\x12&\n!ATOM_NFC_READER_CONFLICT_OCCURRED\x10\xb2\x04\x12\x1e\n\x19\x41TOM_WS_TILE_LIST_CHANGED\x10\xb3\x04\x12.\n)ATOM_GET_TYPE_ACCESSED_WITHOUT_PERMISSION\x10\xb4\x04\x12*\n%ATOM_MOBILE_BUNDLED_APP_INFO_GATHERED\x10\xb6\x04\x12\x30\n+ATOM_WS_WATCH_FACE_COMPLICATION_SET_CHANGED\x10\xb7\x04\x12\x1b\n\x16\x41TOM_MEDIA_DRM_CREATED\x10\xb8\x04\x12\x1b\n\x16\x41TOM_MEDIA_DRM_ERRORED\x10\xb9\x04\x12"\n\x1d\x41TOM_MEDIA_DRM_SESSION_OPENED\x10\xba\x04\x12"\n\x1d\x41TOM_MEDIA_DRM_SESSION_CLOSED\x10\xbb\x04\x12"\n\x1d\x41TOM_USER_SELECTED_RESOLUTION\x10\xbc\x04\x12&\n!ATOM_UNSAFE_INTENT_EVENT_REPORTED\x10\xbd\x04\x12+\n&ATOM_PERFORMANCE_HINT_SESSION_REPORTED\x10\xbe\x04\x12\x31\n,ATOM_MEDIAMETRICS_MIDI_DEVICE_CLOSE_REPORTED\x10\xc0\x04\x12"\n\x1d\x41TOM_BIOMETRIC_TOUCH_REPORTED\x10\xc1\x04\x12-\n(ATOM_HOTWORD_AUDIO_EGRESS_EVENT_REPORTED\x10\xc2\x04\x12\x34\n/ATOM_APP_SEARCH_SCHEMA_MIGRATION_STATS_REPORTED\x10\xc3\x04\x12(\n#ATOM_LOCATION_ENABLED_STATE_CHANGED\x10\xc4\x04\x12\x1e\n\x19\x41TOM_IME_REQUEST_FINISHED\x10\xc5\x04\x12*\n%ATOM_USB_COMPLIANCE_WARNINGS_REPORTED\x10\xc6\x04\x12\'\n"ATOM_APP_SUPPORTED_LOCALES_CHANGED\x10\xc7\x04\x12(\n#ATOM_GRAMMATICAL_INFLECTION_CHANGED\x10\xc8\x04\x12\x31\n,ATOM_MEDIA_PROVIDER_VOLUME_RECOVERY_REPORTED\x10\xca\x04\x12(\n#ATOM_BIOMETRIC_PROPERTIES_COLLECTED\x10\xcb\x04\x12"\n\x1d\x41TOM_KERNEL_WAKEUP_ATTRIBUTED\x10\xcc\x04\x12!\n\x1c\x41TOM_SCREEN_STATE_CHANGED_V2\x10\xcd\x04\x12#\n\x1e\x41TOM_WS_BACKUP_ACTION_REPORTED\x10\xce\x04\x12$\n\x1f\x41TOM_WS_RESTORE_ACTION_REPORTED\x10\xcf\x04\x12*\n%ATOM_DEVICE_LOG_ACCESS_EVENT_REPORTED\x10\xd0\x04\x12\x1f\n\x1a\x41TOM_MEDIA_SESSION_UPDATED\x10\xd2\x04\x12!\n\x1c\x41TOM_WEAR_OOBE_STATE_CHANGED\x10\xd3\x04\x12!\n\x1c\x41TOM_WS_NOTIFICATION_UPDATED\x10\xd4\x04\x12\x39\n4ATOM_NETWORK_VALIDATION_FAILURE_STATS_DAILY_REPORTED\x10\xd9\x04\x12 \n\x1b\x41TOM_WS_COMPLICATION_TAPPED\x10\xda\x04\x12\x1e\n\x19\x41TOM_WS_WEAR_TIME_SESSION\x10\xe2\x04\x12\x1d\n\x18\x41TOM_WIFI_BYTES_TRANSFER\x10\x90N\x12&\n!ATOM_WIFI_BYTES_TRANSFER_BY_FG_BG\x10\x91N\x12\x1f\n\x1a\x41TOM_MOBILE_BYTES_TRANSFER\x10\x92N\x12(\n#ATOM_MOBILE_BYTES_TRANSFER_BY_FG_BG\x10\x93N\x12"\n\x1d\x41TOM_BLUETOOTH_BYTES_TRANSFER\x10\x96N\x12\x19\n\x14\x41TOM_KERNEL_WAKELOCK\x10\x94N\x12\x1f\n\x1a\x41TOM_SUBSYSTEM_SLEEP_STATE\x10\x95N\x12\x1a\n\x15\x41TOM_CPU_TIME_PER_UID\x10\x99N\x12\x1f\n\x1a\x41TOM_CPU_TIME_PER_UID_FREQ\x10\x9aN\x12\x1c\n\x17\x41TOM_WIFI_ACTIVITY_INFO\x10\x9bN\x12\x1d\n\x18\x41TOM_MODEM_ACTIVITY_INFO\x10\x9cN\x12!\n\x1c\x41TOM_BLUETOOTH_ACTIVITY_INFO\x10\x97N\x12\x1e\n\x19\x41TOM_PROCESS_MEMORY_STATE\x10\x9dN\x12!\n\x1c\x41TOM_SYSTEM_ELAPSED_REALTIME\x10\x9eN\x12\x17\n\x12\x41TOM_SYSTEM_UPTIME\x10\x9fN\x12\x19\n\x14\x41TOM_CPU_ACTIVE_TIME\x10\xa0N\x12\x1a\n\x15\x41TOM_CPU_CLUSTER_TIME\x10\xa1N\x12\x14\n\x0f\x41TOM_DISK_SPACE\x10\xa2N\x12$\n\x1f\x41TOM_REMAINING_BATTERY_CAPACITY\x10\xa3N\x12\x1f\n\x1a\x41TOM_FULL_BATTERY_CAPACITY\x10\xa4N\x12\x15\n\x10\x41TOM_TEMPERATURE\x10\xa5N\x12\x16\n\x11\x41TOM_BINDER_CALLS\x10\xa6N\x12!\n\x1c\x41TOM_BINDER_CALLS_EXCEPTIONS\x10\xa7N\x12\x16\n\x11\x41TOM_LOOPER_STATS\x10\xa8N\x12\x14\n\x0f\x41TOM_DISK_STATS\x10\xa9N\x12\x19\n\x14\x41TOM_DIRECTORY_USAGE\x10\xaaN\x12\x12\n\rATOM_APP_SIZE\x10\xabN\x12\x17\n\x12\x41TOM_CATEGORY_SIZE\x10\xacN\x12\x14\n\x0f\x41TOM_PROC_STATS\x10\xadN\x12\x19\n\x14\x41TOM_BATTERY_VOLTAGE\x10\xaeN\x12#\n\x1e\x41TOM_NUM_FINGERPRINTS_ENROLLED\x10\xafN\x12\x11\n\x0c\x41TOM_DISK_IO\x10\xb0N\x12\x17\n\x12\x41TOM_POWER_PROFILE\x10\xb1N\x12\x1d\n\x18\x41TOM_PROC_STATS_PKG_PROC\x10\xb2N\x12\x1a\n\x15\x41TOM_PROCESS_CPU_TIME\x10\xb3N\x12"\n\x1d\x41TOM_CPU_TIME_PER_THREAD_FREQ\x10\xb5N\x12%\n ATOM_ON_DEVICE_POWER_MEASUREMENT\x10\xb6N\x12%\n ATOM_DEVICE_CALCULATED_POWER_USE\x10\xb7N\x12(\n#ATOM_PROCESS_MEMORY_HIGH_WATER_MARK\x10\xbaN\x12\x17\n\x12\x41TOM_BATTERY_LEVEL\x10\xbbN\x12\x1b\n\x16\x41TOM_BUILD_INFORMATION\x10\xbcN\x12\x1d\n\x18\x41TOM_BATTERY_CYCLE_COUNT\x10\xbdN\x12\x1d\n\x18\x41TOM_DEBUG_ELAPSED_CLOCK\x10\xbeN\x12%\n ATOM_DEBUG_FAILING_ELAPSED_CLOCK\x10\xbfN\x12\x1c\n\x17\x41TOM_NUM_FACES_ENROLLED\x10\xc0N\x12\x15\n\x10\x41TOM_ROLE_HOLDER\x10\xc1N\x12$\n\x1f\x41TOM_DANGEROUS_PERMISSION_STATE\x10\xc2N\x12\x14\n\x0f\x41TOM_TRAIN_INFO\x10\xc3N\x12\x1d\n\x18\x41TOM_TIME_ZONE_DATA_INFO\x10\xc4N\x12\x1f\n\x1a\x41TOM_EXTERNAL_STORAGE_INFO\x10\xc5N\x12\x1f\n\x1a\x41TOM_GPU_STATS_GLOBAL_INFO\x10\xc6N\x12\x1c\n\x17\x41TOM_GPU_STATS_APP_INFO\x10\xc7N\x12\x1e\n\x19\x41TOM_SYSTEM_ION_HEAP_SIZE\x10\xc8N\x12\'\n"ATOM_APPS_ON_EXTERNAL_STORAGE_INFO\x10\xc9N\x12\x17\n\x12\x41TOM_FACE_SETTINGS\x10\xcaN\x12\x18\n\x13\x41TOM_COOLING_DEVICE\x10\xcbN\x12\x11\n\x0c\x41TOM_APP_OPS\x10\xccN\x12&\n!ATOM_PROCESS_SYSTEM_ION_HEAP_SIZE\x10\xcdN\x12*\n%ATOM_SURFACEFLINGER_STATS_GLOBAL_INFO\x10\xceN\x12)\n$ATOM_SURFACEFLINGER_STATS_LAYER_INFO\x10\xcfN\x12!\n\x1c\x41TOM_PROCESS_MEMORY_SNAPSHOT\x10\xd0N\x12\x1a\n\x15\x41TOM_VMS_CLIENT_STATS\x10\xd1N\x12#\n\x1e\x41TOM_NOTIFICATION_REMOTE_VIEWS\x10\xd2N\x12,\n\'ATOM_DANGEROUS_PERMISSION_STATE_SAMPLED\x10\xd3N\x12\x18\n\x13\x41TOM_GRAPHICS_STATS\x10\xd4N\x12\x1f\n\x1a\x41TOM_RUNTIME_APP_OP_ACCESS\x10\xd5N\x12\x17\n\x12\x41TOM_ION_HEAP_SIZE\x10\xd6N\x12*\n%ATOM_PACKAGE_NOTIFICATION_PREFERENCES\x10\xd7N\x12\x32\n-ATOM_PACKAGE_NOTIFICATION_CHANNEL_PREFERENCES\x10\xd8N\x12\x38\n3ATOM_PACKAGE_NOTIFICATION_CHANNEL_GROUP_PREFERENCES\x10\xd9N\x12\x14\n\x0f\x41TOM_GNSS_STATS\x10\xdaN\x12\x1c\n\x17\x41TOM_ATTRIBUTED_APP_OPS\x10\xdbN\x12\x1c\n\x17\x41TOM_VOICE_CALL_SESSION\x10\xdcN\x12\x1e\n\x19\x41TOM_VOICE_CALL_RAT_USAGE\x10\xddN\x12\x18\n\x13\x41TOM_SIM_SLOT_STATE\x10\xdeN\x12\'\n"ATOM_SUPPORTED_RADIO_ACCESS_FAMILY\x10\xdfN\x12\x1a\n\x15\x41TOM_SETTING_SNAPSHOT\x10\xe0N\x12\x13\n\x0e\x41TOM_BLOB_INFO\x10\xe1N\x12#\n\x1e\x41TOM_DATA_USAGE_BYTES_TRANSFER\x10\xe2N\x12+\n&ATOM_BYTES_TRANSFER_BY_TAG_AND_METERED\x10\xe3N\x12\x17\n\x12\x41TOM_DND_MODE_RULE\x10\xe4N\x12/\n*ATOM_GENERAL_EXTERNAL_STORAGE_ACCESS_STATS\x10\xe5N\x12\x16\n\x11\x41TOM_INCOMING_SMS\x10\xe6N\x12\x16\n\x11\x41TOM_OUTGOING_SMS\x10\xe7N\x12"\n\x1d\x41TOM_CARRIER_ID_TABLE_VERSION\x10\xe8N\x12\x1b\n\x16\x41TOM_DATA_CALL_SESSION\x10\xe9N\x12 \n\x1b\x41TOM_CELLULAR_SERVICE_STATE\x10\xeaN\x12&\n!ATOM_CELLULAR_DATA_SERVICE_SWITCH\x10\xebN\x12\x17\n\x12\x41TOM_SYSTEM_MEMORY\x10\xecN\x12&\n!ATOM_IMS_REGISTRATION_TERMINATION\x10\xedN\x12 \n\x1b\x41TOM_IMS_REGISTRATION_STATS\x10\xeeN\x12#\n\x1e\x41TOM_CPU_TIME_PER_CLUSTER_FREQ\x10\xefN\x12$\n\x1f\x41TOM_CPU_CYCLES_PER_UID_CLUSTER\x10\xf0N\x12\x1d\n\x18\x41TOM_DEVICE_ROTATED_DATA\x10\xf1N\x12-\n(ATOM_CPU_CYCLES_PER_THREAD_GROUP_CLUSTER\x10\xf2N\x12!\n\x1c\x41TOM_MEDIA_DRM_ACTIVITY_INFO\x10\xf3N\x12$\n\x1f\x41TOM_OEM_MANAGED_BYTES_TRANSFER\x10\xf4N\x12\x1a\n\x15\x41TOM_GNSS_POWER_STATS\x10\xf5N\x12"\n\x1d\x41TOM_TIME_ZONE_DETECTOR_STATE\x10\xf6N\x12!\n\x1c\x41TOM_KEYSTORE2_STORAGE_STATS\x10\xf7N\x12\x18\n\x13\x41TOM_RKP_POOL_STATS\x10\xf8N\x12\x1f\n\x1a\x41TOM_PROCESS_DMABUF_MEMORY\x10\xf9N\x12\x1c\n\x17\x41TOM_PENDING_ALARM_INFO\x10\xfaN\x12$\n\x1f\x41TOM_USER_LEVEL_HIBERNATED_APPS\x10\xfbN\x12"\n\x1d\x41TOM_LAUNCHER_LAYOUT_SNAPSHOT\x10\xfcN\x12 \n\x1b\x41TOM_GLOBAL_HIBERNATED_APPS\x10\xfdN\x12$\n\x1f\x41TOM_INPUT_EVENT_LATENCY_SKETCH\x10\xfeN\x12*\n%ATOM_BATTERY_USAGE_STATS_BEFORE_RESET\x10\xffN\x12)\n$ATOM_BATTERY_USAGE_STATS_SINCE_RESET\x10\x80O\x12\x43\n>ATOM_BATTERY_USAGE_STATS_SINCE_RESET_USING_POWER_PROFILE_MODEL\x10\x81O\x12\'\n"ATOM_INSTALLED_INCREMENTAL_PACKAGE\x10\x82O\x12$\n\x1f\x41TOM_TELEPHONY_NETWORK_REQUESTS\x10\x83O\x12!\n\x1c\x41TOM_APP_SEARCH_STORAGE_INFO\x10\x84O\x12\x10\n\x0b\x41TOM_VMSTAT\x10\x85O\x12\x32\n-ATOM_KEYSTORE2_KEY_CREATION_WITH_GENERAL_INFO\x10\x86O\x12/\n*ATOM_KEYSTORE2_KEY_CREATION_WITH_AUTH_INFO\x10\x87O\x12<\n7ATOM_KEYSTORE2_KEY_CREATION_WITH_PURPOSE_AND_MODES_INFO\x10\x88O\x12&\n!ATOM_KEYSTORE2_ATOM_WITH_OVERFLOW\x10\x89O\x12=\n8ATOM_KEYSTORE2_KEY_OPERATION_WITH_PURPOSE_AND_MODES_INFO\x10\x8aO\x12\x33\n.ATOM_KEYSTORE2_KEY_OPERATION_WITH_GENERAL_INFO\x10\x8bO\x12\x19\n\x14\x41TOM_RKP_ERROR_STATS\x10\x8cO\x12\x1f\n\x1a\x41TOM_KEYSTORE2_CRASH_STATS\x10\x8dO\x12\x1a\n\x15\x41TOM_VENDOR_APEX_INFO\x10\x8eO\x12&\n!ATOM_ACCESSIBILITY_SHORTCUT_STATS\x10\x8fO\x12+\n&ATOM_ACCESSIBILITY_FLOATING_MENU_STATS\x10\x90O\x12&\n!ATOM_DATA_USAGE_BYTES_TRANSFER_V2\x10\x91O\x12\x1c\n\x17\x41TOM_MEDIA_CAPABILITIES\x10\x92O\x12.\n)ATOM_CAR_WATCHDOG_SYSTEM_IO_USAGE_SUMMARY\x10\x93O\x12+\n&ATOM_CAR_WATCHDOG_UID_IO_USAGE_SUMMARY\x10\x94O\x12,\n\'ATOM_IMS_REGISTRATION_FEATURE_TAG_STATS\x10\x95O\x12\'\n"ATOM_RCS_CLIENT_PROVISIONING_STATS\x10\x96O\x12$\n\x1f\x41TOM_RCS_ACS_PROVISIONING_STATS\x10\x97O\x12\x1c\n\x17\x41TOM_SIP_DELEGATE_STATS\x10\x98O\x12)\n$ATOM_SIP_TRANSPORT_FEATURE_TAG_STATS\x10\x99O\x12\x1e\n\x19\x41TOM_SIP_MESSAGE_RESPONSE\x10\x9aO\x12\x1f\n\x1a\x41TOM_SIP_TRANSPORT_SESSION\x10\x9bO\x12-\n(ATOM_IMS_DEDICATED_BEARER_LISTENER_EVENT\x10\x9cO\x12$\n\x1f\x41TOM_IMS_DEDICATED_BEARER_EVENT\x10\x9dO\x12-\n(ATOM_IMS_REGISTRATION_SERVICE_DESC_STATS\x10\x9eO\x12\x19\n\x14\x41TOM_UCE_EVENT_STATS\x10\x9fO\x12\x1f\n\x1a\x41TOM_PRESENCE_NOTIFY_EVENT\x10\xa0O\x12\x13\n\x0e\x41TOM_GBA_EVENT\x10\xa1O\x12\x18\n\x13\x41TOM_PER_SIM_STATUS\x10\xa2O\x12\x1a\n\x15\x41TOM_GPU_WORK_PER_UID\x10\xa3O\x12\x37\n2ATOM_PERSISTENT_URI_PERMISSIONS_AMOUNT_PER_PACKAGE\x10\xa4O\x12\x1f\n\x1a\x41TOM_SIGNED_PARTITION_INFO\x10\xa5O\x12\'\n"ATOM_PINNED_FILE_SIZES_PER_PACKAGE\x10\xa6O\x12%\n ATOM_PENDING_INTENTS_PER_PACKAGE\x10\xa7O\x12\x13\n\x0e\x41TOM_USER_INFO\x10\xa8O\x12\'\n"ATOM_TELEPHONY_NETWORK_REQUESTS_V2\x10\xa9O\x12%\n ATOM_DEVICE_TELEPHONY_PROPERTIES\x10\xaaO\x12.\n)ATOM_REMOTE_KEY_PROVISIONING_ERROR_COUNTS\x10\xabO\x12\x16\n\x11\x41TOM_SAFETY_STATE\x10\xacO\x12\x16\n\x11\x41TOM_INCOMING_MMS\x10\xadO\x12\x16\n\x11\x41TOM_OUTGOING_MMS\x10\xaeO\x12\x19\n\x14\x41TOM_MULTI_USER_INFO\x10\xb0O\x12\x1e\n\x19\x41TOM_NETWORK_BPF_MAP_INFO\x10\xb1O\x12!\n\x1c\x41TOM_OUTGOING_SHORT_CODE_SMS\x10\xb2O\x12#\n\x1e\x41TOM_CONNECTIVITY_STATE_SAMPLE\x10\xb3O\x12\x30\n+ATOM_NETWORK_SELECTION_REMATCH_REASONS_INFO\x10\xb4O\x12\x18\n\x13\x41TOM_GAME_MODE_INFO\x10\xb5O\x12!\n\x1c\x41TOM_GAME_MODE_CONFIGURATION\x10\xb6O\x12\x1c\n\x17\x41TOM_GAME_MODE_LISTENER\x10\xb7O\x12%\n ATOM_NETWORK_SLICE_REQUEST_COUNT\x10\xb8O\x12\x1a\n\x15\x41TOM_WS_TILE_SNAPSHOT\x10\xb9O\x12\x38\n3ATOM_WS_ACTIVE_WATCH_FACE_COMPLICATION_SET_SNAPSHOT\x10\xbaO\x12\x17\n\x12\x41TOM_PROCESS_STATE\x10\xbbO\x12\x1d\n\x18\x41TOM_PROCESS_ASSOCIATION\x10\xbcO\x12$\n\x1f\x41TOM_ADPF_SYSTEM_COMPONENT_INFO\x10\xbdO\x12!\n\x1c\x41TOM_NOTIFICATION_MEMORY_USE\x10\xbeO\x12\x1a\n\x15\x41TOM_HDR_CAPABILITIES\x10\xbfO\x12/\n*ATOM_WS_FAVOURITE_WATCH_FACE_LIST_SNAPSHOT\x10\xc0O\x12!\n\x1c\x41TOM_WIFI_AWARE_NDP_REPORTED\x10\xfe\x04\x12$\n\x1f\x41TOM_WIFI_AWARE_ATTACH_REPORTED\x10\xff\x04\x12&\n!ATOM_WIFI_SELF_RECOVERY_TRIGGERED\x10\x95\x05\x12\x19\n\x14\x41TOM_SOFT_AP_STARTED\x10\xa8\x05\x12\x19\n\x14\x41TOM_SOFT_AP_STOPPED\x10\xa9\x05\x12\x1c\n\x17\x41TOM_WIFI_LOCK_RELEASED\x10\xaf\x05\x12\x1f\n\x1a\x41TOM_WIFI_LOCK_DEACTIVATED\x10\xb0\x05\x12\x1b\n\x16\x41TOM_WIFI_CONFIG_SAVED\x10\xb1\x05\x12+\n&ATOM_WIFI_AWARE_RESOURCE_USING_CHANGED\x10\xb2\x05\x12#\n\x1e\x41TOM_WIFI_AWARE_HAL_API_CALLED\x10\xb3\x05\x12*\n%ATOM_WIFI_LOCAL_ONLY_REQUEST_RECEIVED\x10\xb4\x05\x12\x30\n+ATOM_WIFI_LOCAL_ONLY_REQUEST_SCAN_TRIGGERED\x10\xb5\x05\x12#\n\x1e\x41TOM_WIFI_THREAD_TASK_EXECUTED\x10\xb6\x05\x12\x1c\n\x17\x41TOM_WIFI_STATE_CHANGED\x10\xbc\x05\x12!\n\x1c\x41TOM_WIFI_AWARE_CAPABILITIES\x10\xceO\x12\x1a\n\x15\x41TOM_WIFI_MODULE_INFO\x10\xd1O\x12\x1f\n\x1a\x41TOM_SETTINGS_SPA_REPORTED\x10\xee\x04\x12 \n\x1b\x41TOM_EXPRESS_EVENT_REPORTED\x10\x90\x04\x12+\n&ATOM_EXPRESS_HISTOGRAM_SAMPLE_REPORTED\x10\xd1\x04\x12$\n\x1f\x41TOM_EXPRESS_UID_EVENT_REPORTED\x10\x84\x05\x12/\n*ATOM_EXPRESS_UID_HISTOGRAM_SAMPLE_REPORTED\x10\x92\x05\x12,\n\'ATOM_PERMISSION_RATIONALE_DIALOG_VIEWED\x10\x85\x05\x12\x35\n0ATOM_PERMISSION_RATIONALE_DIALOG_ACTION_REPORTED\x10\x86\x05\x12;\n6ATOM_APP_DATA_SHARING_UPDATES_NOTIFICATION_INTERACTION\x10\x87\x05\x12\x32\n-ATOM_APP_DATA_SHARING_UPDATES_FRAGMENT_VIEWED\x10\x88\x05\x12;\n6ATOM_APP_DATA_SHARING_UPDATES_FRAGMENT_ACTION_REPORTED\x10\x89\x05\x12*\n%ATOM_WS_INCOMING_CALL_ACTION_REPORTED\x10\xf2\x04\x12(\n#ATOM_WS_CALL_DISCONNECTION_REPORTED\x10\xf3\x04\x12#\n\x1e\x41TOM_WS_CALL_DURATION_REPORTED\x10\xf4\x04\x12\x32\n-ATOM_WS_CALL_USER_EXPERIENCE_LATENCY_REPORTED\x10\xf5\x04\x12&\n!ATOM_WS_CALL_INTERACTION_REPORTED\x10\xf6\x04\x12%\n ATOM_FULL_SCREEN_INTENT_LAUNCHED\x10\xf7\x04\x12\x15\n\x10\x41TOM_BAL_ALLOWED\x10\xf8\x04\x12"\n\x1d\x41TOM_IN_TASK_ACTIVITY_STARTED\x10\xad\x05\x12$\n\x1f\x41TOM_CACHED_APPS_HIGH_WATERMARK\x10\xcdO\x12\x1c\n\x17\x41TOM_ODREFRESH_REPORTED\x10\xee\x02\x12\x19\n\x14\x41TOM_ODSIGN_REPORTED\x10\xa4\x04\x12\x1c\n\x17\x41TOM_ART_DATUM_REPORTED\x10\xcc\x02\x12#\n\x1e\x41TOM_ART_DEVICE_DATUM_REPORTED\x10\xa6\x04\x12"\n\x1d\x41TOM_ART_DATUM_DELTA_REPORTED\x10\xb5\x04\x12%\n ATOM_BACKGROUND_DEXOPT_JOB_ENDED\x10\xd3\x03\x12.\n)ATOM_WEAR_ADAPTIVE_SUSPEND_STATS_REPORTED\x10\xeb\x04\x12?\n:ATOM_WEAR_POWER_ANOMALY_SERVICE_OPERATIONAL_STATS_REPORTED\x10\xec\x04\x12\x39\n4ATOM_WEAR_POWER_ANOMALY_SERVICE_EVENT_STATS_REPORTED\x10\xed\x04\x12!\n\x1c\x41TOM_EMERGENCY_STATE_CHANGED\x10\xf9\x04\x12\x1b\n\x16\x41TOM_DND_STATE_CHANGED\x10\x91\x05\x12\x13\n\x0e\x41TOM_MTE_STATE\x10\xc5O\x12\x35\n0ATOM_AD_SERVICES_BACK_COMPAT_GET_TOPICS_REPORTED\x10\xd6\x04\x12G\nBATOM_AD_SERVICES_BACK_COMPAT_EPOCH_COMPUTATION_CLASSIFIER_REPORTED\x10\xd7\x04\x12,\n\'ATOM_AD_SERVICES_MEASUREMENT_DEBUG_KEYS\x10\x80\x05\x12$\n\x1f\x41TOM_AD_SERVICES_ERROR_REPORTED\x10\x96\x05\x12\x38\n3ATOM_AD_SERVICES_BACKGROUND_JOBS_EXECUTION_REPORTED\x10\x97\x05\x12=\n8ATOM_AD_SERVICES_MEASUREMENT_DELAYED_SOURCE_REGISTRATION\x10\xa1\x05\x12-\n(ATOM_AD_SERVICES_MEASUREMENT_ATTRIBUTION\x10\xa2\x05\x12&\n!ATOM_AD_SERVICES_MEASUREMENT_JOBS\x10\xa3\x05\x12)\n$ATOM_AD_SERVICES_MEASUREMENT_WIPEOUT\x10\xa4\x05\x12&\n!ATOM_AD_SERVICES_CONSENT_MIGRATED\x10\xbe\x05\x12\x19\n\x14\x41TOM_RKPD_POOL_STATS\x10\x98\x05\x12\x1f\n\x1a\x41TOM_RKPD_CLIENT_OPERATION\x10\x99\x05\x12$\n\x1f\x41TOM_AUTOFILL_UI_EVENT_REPORTED\x10\xdb\x04\x12(\n#ATOM_AUTOFILL_FILL_REQUEST_REPORTED\x10\xdc\x04\x12)\n$ATOM_AUTOFILL_FILL_RESPONSE_REPORTED\x10\xdd\x04\x12&\n!ATOM_AUTOFILL_SAVE_EVENT_REPORTED\x10\xde\x04\x12$\n\x1f\x41TOM_AUTOFILL_SESSION_COMMITTED\x10\xdf\x04\x12\x36\n1ATOM_AUTOFILL_FIELD_CLASSIFICATION_EVENT_REPORTED\x10\x93\x05\x12&\n!ATOM_TEST_EXTENSION_ATOM_REPORTED\x10\x94\x05\x12\'\n"ATOM_TEST_RESTRICTED_ATOM_REPORTED\x10\xa0\x05\x12$\n\x1f\x41TOM_STATS_SOCKET_LOSS_REPORTED\x10\xf0\x05\x12\x1c\n\x17\x41TOM_PLUGIN_INITIALIZED\x10\x8f\x05\x12%\n ATOM_TV_LOW_POWER_STANDBY_POLICY\x10\xa7\x05\x12&\n!ATOM_LOCKSCREEN_SHORTCUT_SELECTED\x10\xe3\x04\x12\'\n"ATOM_LOCKSCREEN_SHORTCUT_TRIGGERED\x10\xe4\x04\x12 \n\x1b\x41TOM_EMERGENCY_NUMBERS_INFO\x10\xc4O\x12$\n\x1f\x41TOM_QUALIFIED_RAT_LIST_CHANGED\x10\xfa\x04\x12!\n\x1c\x41TOM_QNS_IMS_CALL_DROP_STATS\x10\xfb\x04\x12*\n%ATOM_QNS_FALLBACK_RESTRICTION_CHANGED\x10\xfc\x04\x12*\n%ATOM_QNS_RAT_PREFERENCE_MISMATCH_INFO\x10\xc1O\x12"\n\x1d\x41TOM_QNS_HANDOVER_TIME_MILLIS\x10\xc2O\x12\x1f\n\x1a\x41TOM_QNS_HANDOVER_PINGPONG\x10\xc3O\x12\x1e\n\x19\x41TOM_SATELLITE_CONTROLLER\x10\xc6O\x12\x1b\n\x16\x41TOM_SATELLITE_SESSION\x10\xc7O\x12%\n ATOM_SATELLITE_INCOMING_DATAGRAM\x10\xc8O\x12%\n ATOM_SATELLITE_OUTGOING_DATAGRAM\x10\xc9O\x12\x1d\n\x18\x41TOM_SATELLITE_PROVISION\x10\xcaO\x12+\n&ATOM_SATELLITE_SOS_MESSAGE_RECOMMENDER\x10\xcbO\x12 \n\x1b\x41TOM_IKE_SESSION_TERMINATED\x10\xa6\x05\x12.\n)ATOM_IKE_LIVENESS_CHECK_SESSION_VALIDATED\x10\xf8\x05\x12/\n*ATOM_BLUETOOTH_HASHED_DEVICE_NAME_REPORTED\x10\xe5\x04\x12/\n*ATOM_BLUETOOTH_L2CAP_COC_CLIENT_CONNECTION\x10\xe6\x04\x12/\n*ATOM_BLUETOOTH_L2CAP_COC_SERVER_CONNECTION\x10\xe7\x04\x12(\n#ATOM_BLUETOOTH_LE_SESSION_CONNECTED\x10\x90\x05\x12\x33\n.ATOM_RESTRICTED_BLUETOOTH_DEVICE_NAME_REPORTED\x10\x9a\x05\x12\x30\n+ATOM_BLUETOOTH_PROFILE_CONNECTION_ATTEMPTED\x10\xb8\x05\x12&\n!ATOM_HEALTH_CONNECT_UI_IMPRESSION\x10\xef\x04\x12\'\n"ATOM_HEALTH_CONNECT_UI_INTERACTION\x10\xf0\x04\x12,\n\'ATOM_HEALTH_CONNECT_APP_OPENED_REPORTED\x10\xf1\x04\x12#\n\x1e\x41TOM_HEALTH_CONNECT_API_CALLED\x10\xe8\x04\x12$\n\x1f\x41TOM_HEALTH_CONNECT_USAGE_STATS\x10\xe9\x04\x12&\n!ATOM_HEALTH_CONNECT_STORAGE_STATS\x10\xea\x04\x12$\n\x1f\x41TOM_HEALTH_CONNECT_API_INVOKED\x10\x83\x05\x12#\n\x1e\x41TOM_EXERCISE_ROUTE_API_CALLED\x10\x8e\x05\x12\x13\n\x0e\x41TOM_ATOM_9999\x10\x8fN\x12\x15\n\x0f\x41TOM_ATOM_99999\x10\x9f\x8d\x06\x12/\n*ATOM_THREADNETWORK_TELEMETRY_DATA_REPORTED\x10\xe2\x05\x12+\n&ATOM_THREADNETWORK_TOPO_ENTRY_REPEATED\x10\xe3\x05\x12,\n\'ATOM_THREADNETWORK_DEVICE_INFO_REPORTED\x10\xe4\x05\x12!\n\x1c\x41TOM_EMERGENCY_NUMBER_DIALED\x10\xfd\x04\x12\x1c\n\x17\x41TOM_SANDBOX_API_CALLED\x10\xe8\x03\x12)\n$ATOM_SANDBOX_ACTIVITY_EVENT_OCCURRED\x10\xdf\x05\x12\x1d\n\x18\x41TOM_SANDBOX_SDK_STORAGE\x10\xafO\x12\x1f\n\x1a\x41TOM_CRONET_ENGINE_CREATED\x10\xbf\x05\x12!\n\x1c\x41TOM_CRONET_TRAFFIC_REPORTED\x10\xc0\x05\x12+\n&ATOM_CRONET_ENGINE_BUILDER_INITIALIZED\x10\xfa\x05\x12\'\n"ATOM_CRONET_HTTP_FLAGS_INITIALIZED\x10\xfb\x05\x12\x1c\n\x17\x41TOM_CRONET_INITIALIZED\x10\xfc\x05\x12\'\n"ATOM_DAILY_KEEPALIVE_INFO_REPORTED\x10\x8a\x05\x12$\n\x1f\x41TOM_IP_CLIENT_RA_INFO_REPORTED\x10\x8a\x06\x12#\n\x1e\x41TOM_APF_SESSION_INFO_REPORTED\x10\x89\x06\x12\'\n"ATOM_CREDENTIAL_MANAGER_API_CALLED\x10\xc9\x04\x12\x30\n+ATOM_CREDENTIAL_MANAGER_INIT_PHASE_REPORTED\x10\x8b\x05\x12\x35\n0ATOM_CREDENTIAL_MANAGER_CANDIDATE_PHASE_REPORTED\x10\x8c\x05\x12\x31\n,ATOM_CREDENTIAL_MANAGER_FINAL_PHASE_REPORTED\x10\x8d\x05\x12+\n&ATOM_CREDENTIAL_MANAGER_TOTAL_REPORTED\x10\x9b\x05\x12\x30\n+ATOM_CREDENTIAL_MANAGER_FINALNOUID_REPORTED\x10\x9c\x05\x12)\n$ATOM_CREDENTIAL_MANAGER_GET_REPORTED\x10\x9d\x05\x12\x30\n+ATOM_CREDENTIAL_MANAGER_AUTH_CLICK_REPORTED\x10\x9e\x05\x12)\n$ATOM_CREDENTIAL_MANAGER_APIV2_CALLED\x10\x9f\x05\x12\x1b\n\x16\x41TOM_UWB_ACTIVITY_INFO\x10\xccO\x12\x1f\n\x1a\x41TOM_MEDIA_ACTION_REPORTED\x10\xe0\x04\x12!\n\x1c\x41TOM_MEDIA_CONTROLS_LAUNCHED\x10\xe1\x04\x12/\n*ATOM_MEDIA_CODEC_RECLAIM_REQUEST_COMPLETED\x10\xd8\x04\x12\x1d\n\x18\x41TOM_MEDIA_CODEC_STARTED\x10\x81\x05\x12\x1d\n\x18\x41TOM_MEDIA_CODEC_STOPPED\x10\x82\x05\x12\x1e\n\x19\x41TOM_MEDIA_CODEC_RENDERED\x10\xac\x05*\xa5\x07\n\x0fMeminfoCounters\x12\x17\n\x13MEMINFO_UNSPECIFIED\x10\x00\x12\x15\n\x11MEMINFO_MEM_TOTAL\x10\x01\x12\x14\n\x10MEMINFO_MEM_FREE\x10\x02\x12\x19\n\x15MEMINFO_MEM_AVAILABLE\x10\x03\x12\x13\n\x0fMEMINFO_BUFFERS\x10\x04\x12\x12\n\x0eMEMINFO_CACHED\x10\x05\x12\x17\n\x13MEMINFO_SWAP_CACHED\x10\x06\x12\x12\n\x0eMEMINFO_ACTIVE\x10\x07\x12\x14\n\x10MEMINFO_INACTIVE\x10\x08\x12\x17\n\x13MEMINFO_ACTIVE_ANON\x10\t\x12\x19\n\x15MEMINFO_INACTIVE_ANON\x10\n\x12\x17\n\x13MEMINFO_ACTIVE_FILE\x10\x0b\x12\x19\n\x15MEMINFO_INACTIVE_FILE\x10\x0c\x12\x17\n\x13MEMINFO_UNEVICTABLE\x10\r\x12\x13\n\x0fMEMINFO_MLOCKED\x10\x0e\x12\x16\n\x12MEMINFO_SWAP_TOTAL\x10\x0f\x12\x15\n\x11MEMINFO_SWAP_FREE\x10\x10\x12\x11\n\rMEMINFO_DIRTY\x10\x11\x12\x15\n\x11MEMINFO_WRITEBACK\x10\x12\x12\x16\n\x12MEMINFO_ANON_PAGES\x10\x13\x12\x12\n\x0eMEMINFO_MAPPED\x10\x14\x12\x11\n\rMEMINFO_SHMEM\x10\x15\x12\x10\n\x0cMEMINFO_SLAB\x10\x16\x12\x1c\n\x18MEMINFO_SLAB_RECLAIMABLE\x10\x17\x12\x1e\n\x1aMEMINFO_SLAB_UNRECLAIMABLE\x10\x18\x12\x18\n\x14MEMINFO_KERNEL_STACK\x10\x19\x12\x17\n\x13MEMINFO_PAGE_TABLES\x10\x1a\x12\x18\n\x14MEMINFO_COMMIT_LIMIT\x10\x1b\x12\x17\n\x13MEMINFO_COMMITED_AS\x10\x1c\x12\x19\n\x15MEMINFO_VMALLOC_TOTAL\x10\x1d\x12\x18\n\x14MEMINFO_VMALLOC_USED\x10\x1e\x12\x19\n\x15MEMINFO_VMALLOC_CHUNK\x10\x1f\x12\x15\n\x11MEMINFO_CMA_TOTAL\x10 \x12\x14\n\x10MEMINFO_CMA_FREE\x10!\x12\x0f\n\x0bMEMINFO_GPU\x10"\x12\x10\n\x0cMEMINFO_ZRAM\x10#\x12\x10\n\x0cMEMINFO_MISC\x10$\x12\x14\n\x10MEMINFO_ION_HEAP\x10%\x12\x19\n\x15MEMINFO_ION_HEAP_POOL\x10&*\x81,\n\x0eVmstatCounters\x12\x16\n\x12VMSTAT_UNSPECIFIED\x10\x00\x12\x18\n\x14VMSTAT_NR_FREE_PAGES\x10\x01\x12\x19\n\x15VMSTAT_NR_ALLOC_BATCH\x10\x02\x12\x1b\n\x17VMSTAT_NR_INACTIVE_ANON\x10\x03\x12\x19\n\x15VMSTAT_NR_ACTIVE_ANON\x10\x04\x12\x1b\n\x17VMSTAT_NR_INACTIVE_FILE\x10\x05\x12\x19\n\x15VMSTAT_NR_ACTIVE_FILE\x10\x06\x12\x19\n\x15VMSTAT_NR_UNEVICTABLE\x10\x07\x12\x13\n\x0fVMSTAT_NR_MLOCK\x10\x08\x12\x18\n\x14VMSTAT_NR_ANON_PAGES\x10\t\x12\x14\n\x10VMSTAT_NR_MAPPED\x10\n\x12\x18\n\x14VMSTAT_NR_FILE_PAGES\x10\x0b\x12\x13\n\x0fVMSTAT_NR_DIRTY\x10\x0c\x12\x17\n\x13VMSTAT_NR_WRITEBACK\x10\r\x12\x1e\n\x1aVMSTAT_NR_SLAB_RECLAIMABLE\x10\x0e\x12 \n\x1cVMSTAT_NR_SLAB_UNRECLAIMABLE\x10\x0f\x12\x1e\n\x1aVMSTAT_NR_PAGE_TABLE_PAGES\x10\x10\x12\x1a\n\x16VMSTAT_NR_KERNEL_STACK\x10\x11\x12\x16\n\x12VMSTAT_NR_OVERHEAD\x10\x12\x12\x16\n\x12VMSTAT_NR_UNSTABLE\x10\x13\x12\x14\n\x10VMSTAT_NR_BOUNCE\x10\x14\x12\x1a\n\x16VMSTAT_NR_VMSCAN_WRITE\x10\x15\x12&\n"VMSTAT_NR_VMSCAN_IMMEDIATE_RECLAIM\x10\x16\x12\x1c\n\x18VMSTAT_NR_WRITEBACK_TEMP\x10\x17\x12\x1b\n\x17VMSTAT_NR_ISOLATED_ANON\x10\x18\x12\x1b\n\x17VMSTAT_NR_ISOLATED_FILE\x10\x19\x12\x13\n\x0fVMSTAT_NR_SHMEM\x10\x1a\x12\x15\n\x11VMSTAT_NR_DIRTIED\x10\x1b\x12\x15\n\x11VMSTAT_NR_WRITTEN\x10\x1c\x12\x1b\n\x17VMSTAT_NR_PAGES_SCANNED\x10\x1d\x12\x1d\n\x19VMSTAT_WORKINGSET_REFAULT\x10\x1e\x12\x1e\n\x1aVMSTAT_WORKINGSET_ACTIVATE\x10\x1f\x12!\n\x1dVMSTAT_WORKINGSET_NODERECLAIM\x10 \x12(\n$VMSTAT_NR_ANON_TRANSPARENT_HUGEPAGES\x10!\x12\x16\n\x12VMSTAT_NR_FREE_CMA\x10"\x12\x17\n\x13VMSTAT_NR_SWAPCACHE\x10#\x12\x1d\n\x19VMSTAT_NR_DIRTY_THRESHOLD\x10$\x12(\n$VMSTAT_NR_DIRTY_BACKGROUND_THRESHOLD\x10%\x12\x11\n\rVMSTAT_PGPGIN\x10&\x12\x12\n\x0eVMSTAT_PGPGOUT\x10\'\x12\x17\n\x13VMSTAT_PGPGOUTCLEAN\x10(\x12\x11\n\rVMSTAT_PSWPIN\x10)\x12\x12\n\x0eVMSTAT_PSWPOUT\x10*\x12\x16\n\x12VMSTAT_PGALLOC_DMA\x10+\x12\x19\n\x15VMSTAT_PGALLOC_NORMAL\x10,\x12\x1a\n\x16VMSTAT_PGALLOC_MOVABLE\x10-\x12\x11\n\rVMSTAT_PGFREE\x10.\x12\x15\n\x11VMSTAT_PGACTIVATE\x10/\x12\x17\n\x13VMSTAT_PGDEACTIVATE\x10\x30\x12\x12\n\x0eVMSTAT_PGFAULT\x10\x31\x12\x15\n\x11VMSTAT_PGMAJFAULT\x10\x32\x12\x17\n\x13VMSTAT_PGREFILL_DMA\x10\x33\x12\x1a\n\x16VMSTAT_PGREFILL_NORMAL\x10\x34\x12\x1b\n\x17VMSTAT_PGREFILL_MOVABLE\x10\x35\x12\x1d\n\x19VMSTAT_PGSTEAL_KSWAPD_DMA\x10\x36\x12 \n\x1cVMSTAT_PGSTEAL_KSWAPD_NORMAL\x10\x37\x12!\n\x1dVMSTAT_PGSTEAL_KSWAPD_MOVABLE\x10\x38\x12\x1d\n\x19VMSTAT_PGSTEAL_DIRECT_DMA\x10\x39\x12 \n\x1cVMSTAT_PGSTEAL_DIRECT_NORMAL\x10:\x12!\n\x1dVMSTAT_PGSTEAL_DIRECT_MOVABLE\x10;\x12\x1c\n\x18VMSTAT_PGSCAN_KSWAPD_DMA\x10<\x12\x1f\n\x1bVMSTAT_PGSCAN_KSWAPD_NORMAL\x10=\x12 \n\x1cVMSTAT_PGSCAN_KSWAPD_MOVABLE\x10>\x12\x1c\n\x18VMSTAT_PGSCAN_DIRECT_DMA\x10?\x12\x1f\n\x1bVMSTAT_PGSCAN_DIRECT_NORMAL\x10@\x12 \n\x1cVMSTAT_PGSCAN_DIRECT_MOVABLE\x10\x41\x12!\n\x1dVMSTAT_PGSCAN_DIRECT_THROTTLE\x10\x42\x12\x17\n\x13VMSTAT_PGINODESTEAL\x10\x43\x12\x18\n\x14VMSTAT_SLABS_SCANNED\x10\x44\x12\x1c\n\x18VMSTAT_KSWAPD_INODESTEAL\x10\x45\x12\'\n#VMSTAT_KSWAPD_LOW_WMARK_HIT_QUICKLY\x10\x46\x12(\n$VMSTAT_KSWAPD_HIGH_WMARK_HIT_QUICKLY\x10G\x12\x15\n\x11VMSTAT_PAGEOUTRUN\x10H\x12\x15\n\x11VMSTAT_ALLOCSTALL\x10I\x12\x14\n\x10VMSTAT_PGROTATED\x10J\x12\x19\n\x15VMSTAT_DROP_PAGECACHE\x10K\x12\x14\n\x10VMSTAT_DROP_SLAB\x10L\x12\x1c\n\x18VMSTAT_PGMIGRATE_SUCCESS\x10M\x12\x19\n\x15VMSTAT_PGMIGRATE_FAIL\x10N\x12"\n\x1eVMSTAT_COMPACT_MIGRATE_SCANNED\x10O\x12\x1f\n\x1bVMSTAT_COMPACT_FREE_SCANNED\x10P\x12\x1b\n\x17VMSTAT_COMPACT_ISOLATED\x10Q\x12\x18\n\x14VMSTAT_COMPACT_STALL\x10R\x12\x17\n\x13VMSTAT_COMPACT_FAIL\x10S\x12\x1a\n\x16VMSTAT_COMPACT_SUCCESS\x10T\x12\x1e\n\x1aVMSTAT_COMPACT_DAEMON_WAKE\x10U\x12!\n\x1dVMSTAT_UNEVICTABLE_PGS_CULLED\x10V\x12"\n\x1eVMSTAT_UNEVICTABLE_PGS_SCANNED\x10W\x12"\n\x1eVMSTAT_UNEVICTABLE_PGS_RESCUED\x10X\x12"\n\x1eVMSTAT_UNEVICTABLE_PGS_MLOCKED\x10Y\x12$\n VMSTAT_UNEVICTABLE_PGS_MUNLOCKED\x10Z\x12"\n\x1eVMSTAT_UNEVICTABLE_PGS_CLEARED\x10[\x12#\n\x1fVMSTAT_UNEVICTABLE_PGS_STRANDED\x10\\\x12\x15\n\x11VMSTAT_NR_ZSPAGES\x10]\x12\x16\n\x12VMSTAT_NR_ION_HEAP\x10^\x12\x16\n\x12VMSTAT_NR_GPU_HEAP\x10_\x12\x19\n\x15VMSTAT_ALLOCSTALL_DMA\x10`\x12\x1d\n\x19VMSTAT_ALLOCSTALL_MOVABLE\x10\x61\x12\x1c\n\x18VMSTAT_ALLOCSTALL_NORMAL\x10\x62\x12&\n"VMSTAT_COMPACT_DAEMON_FREE_SCANNED\x10\x63\x12)\n%VMSTAT_COMPACT_DAEMON_MIGRATE_SCANNED\x10\x64\x12\x15\n\x11VMSTAT_NR_FASTRPC\x10\x65\x12$\n VMSTAT_NR_INDIRECTLY_RECLAIMABLE\x10\x66\x12\x1b\n\x17VMSTAT_NR_ION_HEAP_POOL\x10g\x12%\n!VMSTAT_NR_KERNEL_MISC_RECLAIMABLE\x10h\x12%\n!VMSTAT_NR_SHADOW_CALL_STACK_BYTES\x10i\x12\x1d\n\x19VMSTAT_NR_SHMEM_HUGEPAGES\x10j\x12\x1d\n\x19VMSTAT_NR_SHMEM_PMDMAPPED\x10k\x12!\n\x1dVMSTAT_NR_UNRECLAIMABLE_PAGES\x10l\x12\x1e\n\x1aVMSTAT_NR_ZONE_ACTIVE_ANON\x10m\x12\x1e\n\x1aVMSTAT_NR_ZONE_ACTIVE_FILE\x10n\x12 \n\x1cVMSTAT_NR_ZONE_INACTIVE_ANON\x10o\x12 \n\x1cVMSTAT_NR_ZONE_INACTIVE_FILE\x10p\x12\x1e\n\x1aVMSTAT_NR_ZONE_UNEVICTABLE\x10q\x12 \n\x1cVMSTAT_NR_ZONE_WRITE_PENDING\x10r\x12\x13\n\x0fVMSTAT_OOM_KILL\x10s\x12\x15\n\x11VMSTAT_PGLAZYFREE\x10t\x12\x16\n\x12VMSTAT_PGLAZYFREED\x10u\x12\x13\n\x0fVMSTAT_PGREFILL\x10v\x12\x18\n\x14VMSTAT_PGSCAN_DIRECT\x10w\x12\x18\n\x14VMSTAT_PGSCAN_KSWAPD\x10x\x12\x15\n\x11VMSTAT_PGSKIP_DMA\x10y\x12\x19\n\x15VMSTAT_PGSKIP_MOVABLE\x10z\x12\x18\n\x14VMSTAT_PGSKIP_NORMAL\x10{\x12\x19\n\x15VMSTAT_PGSTEAL_DIRECT\x10|\x12\x19\n\x15VMSTAT_PGSTEAL_KSWAPD\x10}\x12\x12\n\x0eVMSTAT_SWAP_RA\x10~\x12\x16\n\x12VMSTAT_SWAP_RA_HIT\x10\x7f\x12\x1e\n\x19VMSTAT_WORKINGSET_RESTORE\x10\x80\x01\x12\x1d\n\x18VMSTAT_ALLOCSTALL_DEVICE\x10\x81\x01\x12\x1c\n\x17VMSTAT_ALLOCSTALL_DMA32\x10\x82\x01\x12\x1b\n\x16VMSTAT_BALLOON_DEFLATE\x10\x83\x01\x12\x1b\n\x16VMSTAT_BALLOON_INFLATE\x10\x84\x01\x12\x1b\n\x16VMSTAT_BALLOON_MIGRATE\x10\x85\x01\x12\x1a\n\x15VMSTAT_CMA_ALLOC_FAIL\x10\x86\x01\x12\x1d\n\x18VMSTAT_CMA_ALLOC_SUCCESS\x10\x87\x01\x12\x1d\n\x18VMSTAT_NR_FILE_HUGEPAGES\x10\x88\x01\x12\x1d\n\x18VMSTAT_NR_FILE_PMDMAPPED\x10\x89\x01\x12 \n\x1bVMSTAT_NR_FOLL_PIN_ACQUIRED\x10\x8a\x01\x12 \n\x1bVMSTAT_NR_FOLL_PIN_RELEASED\x10\x8b\x01\x12#\n\x1eVMSTAT_NR_SEC_PAGE_TABLE_PAGES\x10\x8c\x01\x12 \n\x1bVMSTAT_NR_SHADOW_CALL_STACK\x10\x8d\x01\x12\x19\n\x14VMSTAT_NR_SWAPCACHED\x10\x8e\x01\x12 \n\x1bVMSTAT_NR_THROTTLED_WRITTEN\x10\x8f\x01\x12\x1a\n\x15VMSTAT_PGALLOC_DEVICE\x10\x90\x01\x12\x19\n\x14VMSTAT_PGALLOC_DMA32\x10\x91\x01\x12\x1b\n\x16VMSTAT_PGDEMOTE_DIRECT\x10\x92\x01\x12\x1b\n\x16VMSTAT_PGDEMOTE_KSWAPD\x10\x93\x01\x12\x13\n\x0eVMSTAT_PGREUSE\x10\x94\x01\x12\x17\n\x12VMSTAT_PGSCAN_ANON\x10\x95\x01\x12\x17\n\x12VMSTAT_PGSCAN_FILE\x10\x96\x01\x12\x19\n\x14VMSTAT_PGSKIP_DEVICE\x10\x97\x01\x12\x18\n\x13VMSTAT_PGSKIP_DMA32\x10\x98\x01\x12\x18\n\x13VMSTAT_PGSTEAL_ANON\x10\x99\x01\x12\x18\n\x13VMSTAT_PGSTEAL_FILE\x10\x9a\x01\x12\x1e\n\x19VMSTAT_THP_COLLAPSE_ALLOC\x10\x9b\x01\x12%\n VMSTAT_THP_COLLAPSE_ALLOC_FAILED\x10\x9c\x01\x12#\n\x1eVMSTAT_THP_DEFERRED_SPLIT_PAGE\x10\x9d\x01\x12\x1b\n\x16VMSTAT_THP_FAULT_ALLOC\x10\x9e\x01\x12\x1e\n\x19VMSTAT_THP_FAULT_FALLBACK\x10\x9f\x01\x12%\n VMSTAT_THP_FAULT_FALLBACK_CHARGE\x10\xa0\x01\x12\x1a\n\x15VMSTAT_THP_FILE_ALLOC\x10\xa1\x01\x12\x1d\n\x18VMSTAT_THP_FILE_FALLBACK\x10\xa2\x01\x12$\n\x1fVMSTAT_THP_FILE_FALLBACK_CHARGE\x10\xa3\x01\x12\x1b\n\x16VMSTAT_THP_FILE_MAPPED\x10\xa4\x01\x12\x1e\n\x19VMSTAT_THP_MIGRATION_FAIL\x10\xa5\x01\x12\x1f\n\x1aVMSTAT_THP_MIGRATION_SPLIT\x10\xa6\x01\x12!\n\x1cVMSTAT_THP_MIGRATION_SUCCESS\x10\xa7\x01\x12$\n\x1fVMSTAT_THP_SCAN_EXCEED_NONE_PTE\x10\xa8\x01\x12%\n VMSTAT_THP_SCAN_EXCEED_SHARE_PTE\x10\xa9\x01\x12$\n\x1fVMSTAT_THP_SCAN_EXCEED_SWAP_PTE\x10\xaa\x01\x12\x1a\n\x15VMSTAT_THP_SPLIT_PAGE\x10\xab\x01\x12!\n\x1cVMSTAT_THP_SPLIT_PAGE_FAILED\x10\xac\x01\x12\x19\n\x14VMSTAT_THP_SPLIT_PMD\x10\xad\x01\x12\x16\n\x11VMSTAT_THP_SWPOUT\x10\xae\x01\x12\x1f\n\x1aVMSTAT_THP_SWPOUT_FALLBACK\x10\xaf\x01\x12\x1f\n\x1aVMSTAT_THP_ZERO_PAGE_ALLOC\x10\xb0\x01\x12&\n!VMSTAT_THP_ZERO_PAGE_ALLOC_FAILED\x10\xb1\x01\x12\x1a\n\x15VMSTAT_VMA_LOCK_ABORT\x10\xb2\x01\x12\x19\n\x14VMSTAT_VMA_LOCK_MISS\x10\xb3\x01\x12\x1a\n\x15VMSTAT_VMA_LOCK_RETRY\x10\xb4\x01\x12\x1c\n\x17VMSTAT_VMA_LOCK_SUCCESS\x10\xb5\x01\x12$\n\x1fVMSTAT_WORKINGSET_ACTIVATE_ANON\x10\xb6\x01\x12$\n\x1fVMSTAT_WORKINGSET_ACTIVATE_FILE\x10\xb7\x01\x12\x1c\n\x17VMSTAT_WORKINGSET_NODES\x10\xb8\x01\x12#\n\x1eVMSTAT_WORKINGSET_REFAULT_ANON\x10\xb9\x01\x12#\n\x1eVMSTAT_WORKINGSET_REFAULT_FILE\x10\xba\x01\x12#\n\x1eVMSTAT_WORKINGSET_RESTORE_ANON\x10\xbb\x01\x12#\n\x1eVMSTAT_WORKINGSET_RESTORE_FILE\x10\xbc\x01*H\n\x10TrafficDirection\x12\x13\n\x0f\x44IR_UNSPECIFIED\x10\x00\x12\x0f\n\x0b\x44IR_INGRESS\x10\x01\x12\x0e\n\nDIR_EGRESS\x10\x02*6\n\x0eTrustedOverlay\x12\t\n\x05UNSET\x10\x00\x12\x0c\n\x08\x44ISABLED\x10\x01\x12\x0b\n\x07\x45NABLED\x10\x02*\xbf\x01\n\x12HwcCompositionType\x12\x18\n\x14HWC_TYPE_UNSPECIFIED\x10\x00\x12\x13\n\x0fHWC_TYPE_CLIENT\x10\x01\x12\x13\n\x0fHWC_TYPE_DEVICE\x10\x02\x12\x18\n\x14HWC_TYPE_SOLID_COLOR\x10\x03\x12\x13\n\x0fHWC_TYPE_CURSOR\x10\x04\x12\x15\n\x11HWC_TYPE_SIDEBAND\x10\x05\x12\x1f\n\x1bHWC_TYPE_DISPLAY_DECORATION\x10\x06*\xc8\x05\n\x11\x46traceParseStatus\x12\x1d\n\x19\x46TRACE_STATUS_UNSPECIFIED\x10\x00\x12\x14\n\x10\x46TRACE_STATUS_OK\x10\x01\x12\'\n#FTRACE_STATUS_UNEXPECTED_READ_ERROR\x10\x02\x12#\n\x1f\x46TRACE_STATUS_PARTIAL_PAGE_READ\x10\x03\x12)\n%FTRACE_STATUS_ABI_INVALID_PAGE_HEADER\x10\x04\x12(\n$FTRACE_STATUS_ABI_SHORT_EVENT_HEADER\x10\x05\x12"\n\x1e\x46TRACE_STATUS_ABI_NULL_PADDING\x10\x06\x12*\n&FTRACE_STATUS_ABI_SHORT_PADDING_LENGTH\x10\x07\x12,\n(FTRACE_STATUS_ABI_INVALID_PADDING_LENGTH\x10\x08\x12\'\n#FTRACE_STATUS_ABI_SHORT_TIME_EXTEND\x10\t\x12&\n"FTRACE_STATUS_ABI_SHORT_TIME_STAMP\x10\n\x12\'\n#FTRACE_STATUS_ABI_SHORT_DATA_LENGTH\x10\x0b\x12&\n"FTRACE_STATUS_ABI_ZERO_DATA_LENGTH\x10\x0c\x12)\n%FTRACE_STATUS_ABI_INVALID_DATA_LENGTH\x10\r\x12$\n FTRACE_STATUS_ABI_SHORT_EVENT_ID\x10\x0e\x12"\n\x1e\x46TRACE_STATUS_ABI_END_OVERFLOW\x10\x0f\x12%\n!FTRACE_STATUS_SHORT_COMPACT_EVENT\x10\x10\x12\x1f\n\x1b\x46TRACE_STATUS_INVALID_EVENT\x10\x11*\x91\x01\n\x0b\x46traceClock\x12\x1c\n\x18\x46TRACE_CLOCK_UNSPECIFIED\x10\x00\x12\x18\n\x14\x46TRACE_CLOCK_UNKNOWN\x10\x01\x12\x17\n\x13\x46TRACE_CLOCK_GLOBAL\x10\x02\x12\x16\n\x12\x46TRACE_CLOCK_LOCAL\x10\x03\x12\x19\n\x15\x46TRACE_CLOCK_MONO_RAW\x10\x04*\xb0\x05\n\x1f\x43hromeCompositorSchedulerAction\x12#\n\x1f\x43\x43_SCHEDULER_ACTION_UNSPECIFIED\x10\x00\x12\x1c\n\x18\x43\x43_SCHEDULER_ACTION_NONE\x10\x01\x12-\n)CC_SCHEDULER_ACTION_SEND_BEGIN_MAIN_FRAME\x10\x02\x12\x1e\n\x1a\x43\x43_SCHEDULER_ACTION_COMMIT\x10\x03\x12*\n&CC_SCHEDULER_ACTION_ACTIVATE_SYNC_TREE\x10\x04\x12(\n$CC_SCHEDULER_ACTION_DRAW_IF_POSSIBLE\x10\x05\x12#\n\x1f\x43\x43_SCHEDULER_ACTION_DRAW_FORCED\x10\x06\x12"\n\x1e\x43\x43_SCHEDULER_ACTION_DRAW_ABORT\x10\x07\x12<\n8CC_SCHEDULER_ACTION_BEGIN_LAYER_TREE_FRAME_SINK_CREATION\x10\x08\x12%\n!CC_SCHEDULER_ACTION_PREPARE_TILES\x10\t\x12\x38\n4CC_SCHEDULER_ACTION_INVALIDATE_LAYER_TREE_FRAME_SINK\x10\n\x12\x36\n2CC_SCHEDULER_ACTION_PERFORM_IMPL_SIDE_INVALIDATION\x10\x0b\x12\x42\n>CC_SCHEDULER_ACTION_NOTIFY_BEGIN_MAIN_FRAME_NOT_EXPECTED_UNTIL\x10\x0c\x12\x41\n=CC_SCHEDULER_ACTION_NOTIFY_BEGIN_MAIN_FRAME_NOT_EXPECTED_SOON\x10\r*}\n\x0e\x43hromeRAILMode\x12\x12\n\x0eRAIL_MODE_NONE\x10\x00\x12\x16\n\x12RAIL_MODE_RESPONSE\x10\x01\x12\x17\n\x13RAIL_MODE_ANIMATION\x10\x02\x12\x12\n\x0eRAIL_MODE_IDLE\x10\x03\x12\x12\n\x0eRAIL_MODE_LOAD\x10\x04\x42+Z)github.com/google/perfetto/perfetto_proto' # noqa: E501 +) + +_globals = globals() +_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals) +_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, "perfetto_trace_pb2", _globals) +if not _descriptor._USE_C_DESCRIPTORS: + _globals["DESCRIPTOR"]._options = None + _globals["DESCRIPTOR"]._serialized_options = ( + b"Z)github.com/google/perfetto/perfetto_proto" + ) + _globals["_DATASOURCEDESCRIPTOR"].fields_by_name[ + "gpu_counter_descriptor" + ]._options = None + _globals["_DATASOURCEDESCRIPTOR"].fields_by_name[ + "gpu_counter_descriptor" + ]._serialized_options = b"(\001" + _globals["_DATASOURCEDESCRIPTOR"].fields_by_name[ + "track_event_descriptor" + ]._options = None + _globals["_DATASOURCEDESCRIPTOR"].fields_by_name[ + "track_event_descriptor" + ]._serialized_options = b"(\001" + _globals["_DATASOURCEDESCRIPTOR"].fields_by_name[ + "ftrace_descriptor" + ]._options = None + _globals["_DATASOURCEDESCRIPTOR"].fields_by_name[ + "ftrace_descriptor" + ]._serialized_options = b"(\001" + _globals["_FTRACECONFIG"].fields_by_name[ + "initialize_ksyms_synchronously_for_testing" + ]._options = None + _globals["_FTRACECONFIG"].fields_by_name[ + "initialize_ksyms_synchronously_for_testing" + ]._serialized_options = b"\030\001" + _globals["_PROCESSSTATSCONFIG_QUIRKS"].values_by_name[ + "DISABLE_INITIAL_DUMP" + ]._options = None + _globals["_PROCESSSTATSCONFIG_QUIRKS"].values_by_name[ + "DISABLE_INITIAL_DUMP" + ]._serialized_options = b"\010\001" + _globals["_DATASOURCECONFIG"].fields_by_name["ftrace_config"]._options = None + _globals["_DATASOURCECONFIG"].fields_by_name[ + "ftrace_config" + ]._serialized_options = b"(\001" + _globals["_DATASOURCECONFIG"].fields_by_name["inode_file_config"]._options = None + _globals["_DATASOURCECONFIG"].fields_by_name[ + "inode_file_config" + ]._serialized_options = b"(\001" + _globals["_DATASOURCECONFIG"].fields_by_name["process_stats_config"]._options = None + _globals["_DATASOURCECONFIG"].fields_by_name[ + "process_stats_config" + ]._serialized_options = b"(\001" + _globals["_DATASOURCECONFIG"].fields_by_name["sys_stats_config"]._options = None + _globals["_DATASOURCECONFIG"].fields_by_name[ + "sys_stats_config" + ]._serialized_options = b"(\001" + _globals["_DATASOURCECONFIG"].fields_by_name["heapprofd_config"]._options = None + _globals["_DATASOURCECONFIG"].fields_by_name[ + "heapprofd_config" + ]._serialized_options = b"(\001" + _globals["_DATASOURCECONFIG"].fields_by_name["java_hprof_config"]._options = None + _globals["_DATASOURCECONFIG"].fields_by_name[ + "java_hprof_config" + ]._serialized_options = b"(\001" + _globals["_DATASOURCECONFIG"].fields_by_name["android_power_config"]._options = None + _globals["_DATASOURCECONFIG"].fields_by_name[ + "android_power_config" + ]._serialized_options = b"(\001" + _globals["_DATASOURCECONFIG"].fields_by_name["android_log_config"]._options = None + _globals["_DATASOURCECONFIG"].fields_by_name[ + "android_log_config" + ]._serialized_options = b"(\001" + _globals["_DATASOURCECONFIG"].fields_by_name["gpu_counter_config"]._options = None + _globals["_DATASOURCECONFIG"].fields_by_name[ + "gpu_counter_config" + ]._serialized_options = b"(\001" + _globals["_DATASOURCECONFIG"].fields_by_name[ + "android_game_intervention_list_config" + ]._options = None + _globals["_DATASOURCECONFIG"].fields_by_name[ + "android_game_intervention_list_config" + ]._serialized_options = b"(\001" + _globals["_DATASOURCECONFIG"].fields_by_name["packages_list_config"]._options = None + _globals["_DATASOURCECONFIG"].fields_by_name[ + "packages_list_config" + ]._serialized_options = b"(\001" + _globals["_DATASOURCECONFIG"].fields_by_name["perf_event_config"]._options = None + _globals["_DATASOURCECONFIG"].fields_by_name[ + "perf_event_config" + ]._serialized_options = b"(\001" + _globals["_DATASOURCECONFIG"].fields_by_name["vulkan_memory_config"]._options = None + _globals["_DATASOURCECONFIG"].fields_by_name[ + "vulkan_memory_config" + ]._serialized_options = b"(\001" + _globals["_DATASOURCECONFIG"].fields_by_name["track_event_config"]._options = None + _globals["_DATASOURCECONFIG"].fields_by_name[ + "track_event_config" + ]._serialized_options = b"(\001" + _globals["_DATASOURCECONFIG"].fields_by_name[ + "android_polled_state_config" + ]._options = None + _globals["_DATASOURCECONFIG"].fields_by_name[ + "android_polled_state_config" + ]._serialized_options = b"(\001" + _globals["_DATASOURCECONFIG"].fields_by_name[ + "android_system_property_config" + ]._options = None + _globals["_DATASOURCECONFIG"].fields_by_name[ + "android_system_property_config" + ]._serialized_options = b"(\001" + _globals["_DATASOURCECONFIG"].fields_by_name[ + "statsd_tracing_config" + ]._options = None + _globals["_DATASOURCECONFIG"].fields_by_name[ + "statsd_tracing_config" + ]._serialized_options = b"(\001" + _globals["_DATASOURCECONFIG"].fields_by_name["v8_config"]._options = None + _globals["_DATASOURCECONFIG"].fields_by_name[ + "v8_config" + ]._serialized_options = b"(\001" + _globals["_DATASOURCECONFIG"].fields_by_name[ + "network_packet_trace_config" + ]._options = None + _globals["_DATASOURCECONFIG"].fields_by_name[ + "network_packet_trace_config" + ]._serialized_options = b"(\001" + _globals["_DATASOURCECONFIG"].fields_by_name[ + "surfaceflinger_layers_config" + ]._options = None + _globals["_DATASOURCECONFIG"].fields_by_name[ + "surfaceflinger_layers_config" + ]._serialized_options = b"(\001" + _globals["_DATASOURCECONFIG"].fields_by_name[ + "surfaceflinger_transactions_config" + ]._options = None + _globals["_DATASOURCECONFIG"].fields_by_name[ + "surfaceflinger_transactions_config" + ]._serialized_options = b"(\001" + _globals["_DATASOURCECONFIG"].fields_by_name[ + "android_sdk_sysprop_guard_config" + ]._options = None + _globals["_DATASOURCECONFIG"].fields_by_name[ + "android_sdk_sysprop_guard_config" + ]._serialized_options = b"(\001" + _globals["_DATASOURCECONFIG"].fields_by_name["etw_config"]._options = None + _globals["_DATASOURCECONFIG"].fields_by_name[ + "etw_config" + ]._serialized_options = b"(\001" + _globals["_DATASOURCECONFIG"].fields_by_name["protolog_config"]._options = None + _globals["_DATASOURCECONFIG"].fields_by_name[ + "protolog_config" + ]._serialized_options = b"(\001" + _globals["_DATASOURCECONFIG"].fields_by_name[ + "android_input_event_config" + ]._options = None + _globals["_DATASOURCECONFIG"].fields_by_name[ + "android_input_event_config" + ]._serialized_options = b"(\001" + _globals["_DATASOURCECONFIG"].fields_by_name["pixel_modem_config"]._options = None + _globals["_DATASOURCECONFIG"].fields_by_name[ + "pixel_modem_config" + ]._serialized_options = b"(\001" + _globals["_DATASOURCECONFIG"].fields_by_name["windowmanager_config"]._options = None + _globals["_DATASOURCECONFIG"].fields_by_name[ + "windowmanager_config" + ]._serialized_options = b"(\001" + _globals["_TRACECONFIG_GUARDRAILOVERRIDES"].fields_by_name[ + "max_upload_per_day_bytes" + ]._options = None + _globals["_TRACECONFIG_GUARDRAILOVERRIDES"].fields_by_name[ + "max_upload_per_day_bytes" + ]._serialized_options = b"\030\001" + _globals["_TRACECONFIG_INCIDENTREPORTCONFIG"].fields_by_name[ + "skip_dropbox" + ]._options = None + _globals["_TRACECONFIG_INCIDENTREPORTCONFIG"].fields_by_name[ + "skip_dropbox" + ]._serialized_options = b"\030\001" + _globals["_TRACECONFIG"].fields_by_name["trace_uuid_msb"]._options = None + _globals["_TRACECONFIG"].fields_by_name[ + "trace_uuid_msb" + ]._serialized_options = b"\030\001" + _globals["_TRACECONFIG"].fields_by_name["trace_uuid_lsb"]._options = None + _globals["_TRACECONFIG"].fields_by_name[ + "trace_uuid_lsb" + ]._serialized_options = b"\030\001" + _globals["_TRACESTATS_WRITERSTATS"].fields_by_name[ + "chunk_payload_histogram_counts" + ]._options = None + _globals["_TRACESTATS_WRITERSTATS"].fields_by_name[ + "chunk_payload_histogram_counts" + ]._serialized_options = b"\020\001" + _globals["_TRACESTATS_WRITERSTATS"].fields_by_name[ + "chunk_payload_histogram_sum" + ]._options = None + _globals["_TRACESTATS_WRITERSTATS"].fields_by_name[ + "chunk_payload_histogram_sum" + ]._serialized_options = b"\020\001" + _globals["_NETWORKPACKETBUNDLE"].fields_by_name["packet_timestamps"]._options = None + _globals["_NETWORKPACKETBUNDLE"].fields_by_name[ + "packet_timestamps" + ]._serialized_options = b"\020\001" + _globals["_NETWORKPACKETBUNDLE"].fields_by_name["packet_lengths"]._options = None + _globals["_NETWORKPACKETBUNDLE"].fields_by_name[ + "packet_lengths" + ]._serialized_options = b"\020\001" + _globals["_INPUTWINDOWINFOPROTO"].fields_by_name["can_receive_keys"]._options = None + _globals["_INPUTWINDOWINFOPROTO"].fields_by_name[ + "can_receive_keys" + ]._serialized_options = b"\030\001" + _globals["_INPUTWINDOWINFOPROTO"].fields_by_name["window_x_scale"]._options = None + _globals["_INPUTWINDOWINFOPROTO"].fields_by_name[ + "window_x_scale" + ]._serialized_options = b"\030\001" + _globals["_INPUTWINDOWINFOPROTO"].fields_by_name["window_y_scale"]._options = None + _globals["_INPUTWINDOWINFOPROTO"].fields_by_name[ + "window_y_scale" + ]._serialized_options = b"\030\001" + _globals["_COLORTRANSFORMPROTO"].fields_by_name["val"]._options = None + _globals["_COLORTRANSFORMPROTO"].fields_by_name[ + "val" + ]._serialized_options = b"\020\001" + _globals["_LAYERPROTO_METADATAENTRY"]._options = None + _globals["_LAYERPROTO_METADATAENTRY"]._serialized_options = b"8\001" + _globals["_LAYERPROTO"].fields_by_name["children"]._options = None + _globals["_LAYERPROTO"].fields_by_name["children"]._serialized_options = b"\020\001" + _globals["_LAYERPROTO"].fields_by_name["relatives"]._options = None + _globals["_LAYERPROTO"].fields_by_name[ + "relatives" + ]._serialized_options = b"\020\001" + _globals["_LAYERPROTO"].fields_by_name["final_crop"]._options = None + _globals["_LAYERPROTO"].fields_by_name[ + "final_crop" + ]._serialized_options = b"\030\001" + _globals["_LAYERPROTO"].fields_by_name["window_type"]._options = None + _globals["_LAYERPROTO"].fields_by_name[ + "window_type" + ]._serialized_options = b"\030\001" + _globals["_LAYERPROTO"].fields_by_name["app_id"]._options = None + _globals["_LAYERPROTO"].fields_by_name["app_id"]._serialized_options = b"\030\001" + _globals["_CHROMEEVENTBUNDLE"].fields_by_name["trace_events"]._options = None + _globals["_CHROMEEVENTBUNDLE"].fields_by_name[ + "trace_events" + ]._serialized_options = b"\030\001" + _globals["_CHROMEEVENTBUNDLE"].fields_by_name["string_table"]._options = None + _globals["_CHROMEEVENTBUNDLE"].fields_by_name[ + "string_table" + ]._serialized_options = b"\030\001" + _globals["_FTRACEEVENTBUNDLE_COMPACTSCHED"].fields_by_name[ + "switch_timestamp" + ]._options = None + _globals["_FTRACEEVENTBUNDLE_COMPACTSCHED"].fields_by_name[ + "switch_timestamp" + ]._serialized_options = b"\020\001" + _globals["_FTRACEEVENTBUNDLE_COMPACTSCHED"].fields_by_name[ + "switch_prev_state" + ]._options = None + _globals["_FTRACEEVENTBUNDLE_COMPACTSCHED"].fields_by_name[ + "switch_prev_state" + ]._serialized_options = b"\020\001" + _globals["_FTRACEEVENTBUNDLE_COMPACTSCHED"].fields_by_name[ + "switch_next_pid" + ]._options = None + _globals["_FTRACEEVENTBUNDLE_COMPACTSCHED"].fields_by_name[ + "switch_next_pid" + ]._serialized_options = b"\020\001" + _globals["_FTRACEEVENTBUNDLE_COMPACTSCHED"].fields_by_name[ + "switch_next_prio" + ]._options = None + _globals["_FTRACEEVENTBUNDLE_COMPACTSCHED"].fields_by_name[ + "switch_next_prio" + ]._serialized_options = b"\020\001" + _globals["_FTRACEEVENTBUNDLE_COMPACTSCHED"].fields_by_name[ + "switch_next_comm_index" + ]._options = None + _globals["_FTRACEEVENTBUNDLE_COMPACTSCHED"].fields_by_name[ + "switch_next_comm_index" + ]._serialized_options = b"\020\001" + _globals["_FTRACEEVENTBUNDLE_COMPACTSCHED"].fields_by_name[ + "waking_timestamp" + ]._options = None + _globals["_FTRACEEVENTBUNDLE_COMPACTSCHED"].fields_by_name[ + "waking_timestamp" + ]._serialized_options = b"\020\001" + _globals["_FTRACEEVENTBUNDLE_COMPACTSCHED"].fields_by_name[ + "waking_pid" + ]._options = None + _globals["_FTRACEEVENTBUNDLE_COMPACTSCHED"].fields_by_name[ + "waking_pid" + ]._serialized_options = b"\020\001" + _globals["_FTRACEEVENTBUNDLE_COMPACTSCHED"].fields_by_name[ + "waking_target_cpu" + ]._options = None + _globals["_FTRACEEVENTBUNDLE_COMPACTSCHED"].fields_by_name[ + "waking_target_cpu" + ]._serialized_options = b"\020\001" + _globals["_FTRACEEVENTBUNDLE_COMPACTSCHED"].fields_by_name[ + "waking_prio" + ]._options = None + _globals["_FTRACEEVENTBUNDLE_COMPACTSCHED"].fields_by_name[ + "waking_prio" + ]._serialized_options = b"\020\001" + _globals["_FTRACEEVENTBUNDLE_COMPACTSCHED"].fields_by_name[ + "waking_comm_index" + ]._options = None + _globals["_FTRACEEVENTBUNDLE_COMPACTSCHED"].fields_by_name[ + "waking_comm_index" + ]._serialized_options = b"\020\001" + _globals["_FTRACEEVENTBUNDLE_COMPACTSCHED"].fields_by_name[ + "waking_common_flags" + ]._options = None + _globals["_FTRACEEVENTBUNDLE_COMPACTSCHED"].fields_by_name[ + "waking_common_flags" + ]._serialized_options = b"\020\001" + _globals["_GPURENDERSTAGEEVENT"].fields_by_name["specifications"]._options = None + _globals["_GPURENDERSTAGEEVENT"].fields_by_name[ + "specifications" + ]._serialized_options = b"\030\001" + _globals["_GPURENDERSTAGEEVENT"].fields_by_name["hw_queue_id"]._options = None + _globals["_GPURENDERSTAGEEVENT"].fields_by_name[ + "hw_queue_id" + ]._serialized_options = b"\030\001" + _globals["_GPURENDERSTAGEEVENT"].fields_by_name["stage_id"]._options = None + _globals["_GPURENDERSTAGEEVENT"].fields_by_name[ + "stage_id" + ]._serialized_options = b"\030\001" + _globals["_CHROMELATENCYINFO_STEP"].values_by_name[ + "STEP_DRAW_AND_SWAP" + ]._options = None + _globals["_CHROMELATENCYINFO_STEP"].values_by_name[ + "STEP_DRAW_AND_SWAP" + ]._serialized_options = b"\010\001" + _globals["_CHROMELATENCYINFO_STEP"].values_by_name[ + "STEP_FINISHED_SWAP_BUFFERS" + ]._options = None + _globals["_CHROMELATENCYINFO_STEP"].values_by_name[ + "STEP_FINISHED_SWAP_BUFFERS" + ]._serialized_options = b"\010\001" + _globals["_TRACKEVENT"].fields_by_name["flow_ids_old"]._options = None + _globals["_TRACKEVENT"].fields_by_name[ + "flow_ids_old" + ]._serialized_options = b"\030\001" + _globals["_TRACKEVENT"].fields_by_name["terminating_flow_ids_old"]._options = None + _globals["_TRACKEVENT"].fields_by_name[ + "terminating_flow_ids_old" + ]._serialized_options = b"\030\001" + _globals["_HEAPGRAPHROOT"].fields_by_name["object_ids"]._options = None + _globals["_HEAPGRAPHROOT"].fields_by_name[ + "object_ids" + ]._serialized_options = b"\020\001" + _globals["_HEAPGRAPHTYPE"].fields_by_name["reference_field_id"]._options = None + _globals["_HEAPGRAPHTYPE"].fields_by_name[ + "reference_field_id" + ]._serialized_options = b"\020\001" + _globals["_HEAPGRAPHOBJECT"].fields_by_name["reference_field_id"]._options = None + _globals["_HEAPGRAPHOBJECT"].fields_by_name[ + "reference_field_id" + ]._serialized_options = b"\020\001" + _globals["_HEAPGRAPHOBJECT"].fields_by_name["reference_object_id"]._options = None + _globals["_HEAPGRAPHOBJECT"].fields_by_name[ + "reference_object_id" + ]._serialized_options = b"\020\001" + _globals["_CHROMEHISTORGRAMTRANSLATIONTABLE_HASHTONAMEENTRY"]._options = None + _globals[ + "_CHROMEHISTORGRAMTRANSLATIONTABLE_HASHTONAMEENTRY" + ]._serialized_options = b"8\001" + _globals["_CHROMEUSEREVENTTRANSLATIONTABLE_ACTIONHASHTONAMEENTRY"]._options = None + _globals[ + "_CHROMEUSEREVENTTRANSLATIONTABLE_ACTIONHASHTONAMEENTRY" + ]._serialized_options = b"8\001" + _globals["_CHROMEPERFORMANCEMARKTRANSLATIONTABLE_SITEHASHTONAMEENTRY"]._options = ( + None + ) + _globals[ + "_CHROMEPERFORMANCEMARKTRANSLATIONTABLE_SITEHASHTONAMEENTRY" + ]._serialized_options = b"8\001" + _globals["_CHROMEPERFORMANCEMARKTRANSLATIONTABLE_MARKHASHTONAMEENTRY"]._options = ( + None + ) + _globals[ + "_CHROMEPERFORMANCEMARKTRANSLATIONTABLE_MARKHASHTONAMEENTRY" + ]._serialized_options = b"8\001" + _globals["_SLICENAMETRANSLATIONTABLE_RAWTODEOBFUSCATEDNAMEENTRY"]._options = None + _globals[ + "_SLICENAMETRANSLATIONTABLE_RAWTODEOBFUSCATEDNAMEENTRY" + ]._serialized_options = b"8\001" + _globals[ + "_PROCESSTRACKNAMETRANSLATIONTABLE_RAWTODEOBFUSCATEDNAMEENTRY" + ]._options = None + _globals[ + "_PROCESSTRACKNAMETRANSLATIONTABLE_RAWTODEOBFUSCATEDNAMEENTRY" + ]._serialized_options = b"8\001" + _globals["_BUILTINCLOCK"]._serialized_start = 197959 + _globals["_BUILTINCLOCK"]._serialized_end = 198250 + _globals["_ANDROIDLOGID"]._serialized_start = 198253 + _globals["_ANDROIDLOGID"]._serialized_end = 198395 + _globals["_ANDROIDLOGPRIORITY"]._serialized_start = 198398 + _globals["_ANDROIDLOGPRIORITY"]._serialized_end = 198553 + _globals["_PROTOLOGLEVEL"]._serialized_start = 198556 + _globals["_PROTOLOGLEVEL"]._serialized_end = 198755 + _globals["_ATOMID"]._serialized_start = 198759 + _globals["_ATOMID"]._serialized_end = 233401 + _globals["_MEMINFOCOUNTERS"]._serialized_start = 233404 + _globals["_MEMINFOCOUNTERS"]._serialized_end = 234337 + _globals["_VMSTATCOUNTERS"]._serialized_start = 234340 + _globals["_VMSTATCOUNTERS"]._serialized_end = 239973 + _globals["_TRAFFICDIRECTION"]._serialized_start = 239975 + _globals["_TRAFFICDIRECTION"]._serialized_end = 240047 + _globals["_TRUSTEDOVERLAY"]._serialized_start = 240049 + _globals["_TRUSTEDOVERLAY"]._serialized_end = 240103 + _globals["_HWCCOMPOSITIONTYPE"]._serialized_start = 240106 + _globals["_HWCCOMPOSITIONTYPE"]._serialized_end = 240297 + _globals["_FTRACEPARSESTATUS"]._serialized_start = 240300 + _globals["_FTRACEPARSESTATUS"]._serialized_end = 241012 + _globals["_FTRACECLOCK"]._serialized_start = 241015 + _globals["_FTRACECLOCK"]._serialized_end = 241160 + _globals["_CHROMECOMPOSITORSCHEDULERACTION"]._serialized_start = 241163 + _globals["_CHROMECOMPOSITORSCHEDULERACTION"]._serialized_end = 241851 + _globals["_CHROMERAILMODE"]._serialized_start = 241853 + _globals["_CHROMERAILMODE"]._serialized_end = 241978 + _globals["_FTRACEDESCRIPTOR"]._serialized_start = 42 + _globals["_FTRACEDESCRIPTOR"]._serialized_end = 190 + _globals["_FTRACEDESCRIPTOR_ATRACECATEGORY"]._serialized_start = 139 + _globals["_FTRACEDESCRIPTOR_ATRACECATEGORY"]._serialized_end = 190 + _globals["_GPUCOUNTERDESCRIPTOR"]._serialized_start = 193 + _globals["_GPUCOUNTERDESCRIPTOR"]._serialized_end = 1655 + _globals["_GPUCOUNTERDESCRIPTOR_GPUCOUNTERSPEC"]._serialized_start = 462 + _globals["_GPUCOUNTERDESCRIPTOR_GPUCOUNTERSPEC"]._serialized_end = 860 + _globals["_GPUCOUNTERDESCRIPTOR_GPUCOUNTERBLOCK"]._serialized_start = 862 + _globals["_GPUCOUNTERDESCRIPTOR_GPUCOUNTERBLOCK"]._serialized_end = 977 + _globals["_GPUCOUNTERDESCRIPTOR_GPUCOUNTERGROUP"]._serialized_start = 979 + _globals["_GPUCOUNTERDESCRIPTOR_GPUCOUNTERGROUP"]._serialized_end = 1096 + _globals["_GPUCOUNTERDESCRIPTOR_MEASUREUNIT"]._serialized_start = 1099 + _globals["_GPUCOUNTERDESCRIPTOR_MEASUREUNIT"]._serialized_end = 1655 + _globals["_TRACKEVENTCATEGORY"]._serialized_start = 1657 + _globals["_TRACKEVENTCATEGORY"]._serialized_end = 1726 + _globals["_TRACKEVENTDESCRIPTOR"]._serialized_start = 1728 + _globals["_TRACKEVENTDESCRIPTOR"]._serialized_end = 1817 + _globals["_DATASOURCEDESCRIPTOR"]._serialized_start = 1820 + _globals["_DATASOURCEDESCRIPTOR"]._serialized_end = 2202 + _globals["_TRACINGSERVICESTATE"]._serialized_start = 2205 + _globals["_TRACINGSERVICESTATE"]._serialized_end = 3012 + _globals["_TRACINGSERVICESTATE_PRODUCER"]._serialized_start = 2564 + _globals["_TRACINGSERVICESTATE_PRODUCER"]._serialized_end = 2647 + _globals["_TRACINGSERVICESTATE_DATASOURCE"]._serialized_start = 2649 + _globals["_TRACINGSERVICESTATE_DATASOURCE"]._serialized_end = 2744 + _globals["_TRACINGSERVICESTATE_TRACINGSESSION"]._serialized_start = 2747 + _globals["_TRACINGSERVICESTATE_TRACINGSESSION"]._serialized_end = 3012 + _globals["_ANDROIDGAMEINTERVENTIONLISTCONFIG"]._serialized_start = 3014 + _globals["_ANDROIDGAMEINTERVENTIONLISTCONFIG"]._serialized_end = 3078 + _globals["_ANDROIDINPUTEVENTCONFIG"]._serialized_start = 3081 + _globals["_ANDROIDINPUTEVENTCONFIG"]._serialized_end = 3676 + _globals["_ANDROIDINPUTEVENTCONFIG_TRACERULE"]._serialized_start = 3323 + _globals["_ANDROIDINPUTEVENTCONFIG_TRACERULE"]._serialized_end = 3523 + _globals["_ANDROIDINPUTEVENTCONFIG_TRACEMODE"]._serialized_start = 3525 + _globals["_ANDROIDINPUTEVENTCONFIG_TRACEMODE"]._serialized_end = 3588 + _globals["_ANDROIDINPUTEVENTCONFIG_TRACELEVEL"]._serialized_start = 3590 + _globals["_ANDROIDINPUTEVENTCONFIG_TRACELEVEL"]._serialized_end = 3676 + _globals["_ANDROIDLOGCONFIG"]._serialized_start = 3679 + _globals["_ANDROIDLOGCONFIG"]._serialized_end = 3827 + _globals["_ANDROIDPOLLEDSTATECONFIG"]._serialized_start = 3829 + _globals["_ANDROIDPOLLEDSTATECONFIG"]._serialized_end = 3872 + _globals["_ANDROIDSDKSYSPROPGUARDCONFIG"]._serialized_start = 3875 + _globals["_ANDROIDSDKSYSPROPGUARDCONFIG"]._serialized_end = 4013 + _globals["_ANDROIDSYSTEMPROPERTYCONFIG"]._serialized_start = 4015 + _globals["_ANDROIDSYSTEMPROPERTYCONFIG"]._serialized_end = 4084 + _globals["_NETWORKPACKETTRACECONFIG"]._serialized_start = 4087 + _globals["_NETWORKPACKETTRACECONFIG"]._serialized_end = 4258 + _globals["_PACKAGESLISTCONFIG"]._serialized_start = 4260 + _globals["_PACKAGESLISTCONFIG"]._serialized_end = 4309 + _globals["_PIXELMODEMCONFIG"]._serialized_start = 4312 + _globals["_PIXELMODEMCONFIG"]._serialized_end = 4572 + _globals["_PIXELMODEMCONFIG_EVENTGROUP"]._serialized_start = 4464 + _globals["_PIXELMODEMCONFIG_EVENTGROUP"]._serialized_end = 4572 + _globals["_PROTOLOGCONFIG"]._serialized_start = 4575 + _globals["_PROTOLOGCONFIG"]._serialized_end = 4823 + _globals["_PROTOLOGCONFIG_TRACINGMODE"]._serialized_start = 4781 + _globals["_PROTOLOGCONFIG_TRACINGMODE"]._serialized_end = 4823 + _globals["_PROTOLOGGROUP"]._serialized_start = 4825 + _globals["_PROTOLOGGROUP"]._serialized_end = 4938 + _globals["_SURFACEFLINGERLAYERSCONFIG"]._serialized_start = 4941 + _globals["_SURFACEFLINGERLAYERSCONFIG"]._serialized_end = 5437 + _globals["_SURFACEFLINGERLAYERSCONFIG_MODE"]._serialized_start = 5111 + _globals["_SURFACEFLINGERLAYERSCONFIG_MODE"]._serialized_end = 5226 + _globals["_SURFACEFLINGERLAYERSCONFIG_TRACEFLAG"]._serialized_start = 5229 + _globals["_SURFACEFLINGERLAYERSCONFIG_TRACEFLAG"]._serialized_end = 5437 + _globals["_SURFACEFLINGERTRANSACTIONSCONFIG"]._serialized_start = 5440 + _globals["_SURFACEFLINGERTRANSACTIONSCONFIG"]._serialized_end = 5612 + _globals["_SURFACEFLINGERTRANSACTIONSCONFIG_MODE"]._serialized_start = 5546 + _globals["_SURFACEFLINGERTRANSACTIONSCONFIG_MODE"]._serialized_end = 5612 + _globals["_WINDOWMANAGERCONFIG"]._serialized_start = 5615 + _globals["_WINDOWMANAGERCONFIG"]._serialized_end = 6018 + _globals["_WINDOWMANAGERCONFIG_LOGFREQUENCY"]._serialized_start = 5779 + _globals["_WINDOWMANAGERCONFIG_LOGFREQUENCY"]._serialized_end = 5911 + _globals["_WINDOWMANAGERCONFIG_LOGLEVEL"]._serialized_start = 5913 + _globals["_WINDOWMANAGERCONFIG_LOGLEVEL"]._serialized_end = 6018 + _globals["_CHROMECONFIG"]._serialized_start = 6021 + _globals["_CHROMECONFIG"]._serialized_end = 6295 + _globals["_CHROMECONFIG_CLIENTPRIORITY"]._serialized_start = 6230 + _globals["_CHROMECONFIG_CLIENTPRIORITY"]._serialized_end = 6295 + _globals["_V8CONFIG"]._serialized_start = 6297 + _globals["_V8CONFIG"]._serialized_end = 6361 + _globals["_ETWCONFIG"]._serialized_start = 6363 + _globals["_ETWCONFIG"]._serialized_end = 6478 + _globals["_ETWCONFIG_KERNELFLAG"]._serialized_start = 6437 + _globals["_ETWCONFIG_KERNELFLAG"]._serialized_end = 6478 + _globals["_FTRACECONFIG"]._serialized_start = 6481 + _globals["_FTRACECONFIG"]._serialized_end = 7651 + _globals["_FTRACECONFIG_COMPACTSCHEDCONFIG"]._serialized_start = 7267 + _globals["_FTRACECONFIG_COMPACTSCHEDCONFIG"]._serialized_end = 7304 + _globals["_FTRACECONFIG_PRINTFILTER"]._serialized_start = 7307 + _globals["_FTRACECONFIG_PRINTFILTER"]._serialized_end = 7565 + _globals["_FTRACECONFIG_PRINTFILTER_RULE"]._serialized_start = 7386 + _globals["_FTRACECONFIG_PRINTFILTER_RULE"]._serialized_end = 7565 + _globals["_FTRACECONFIG_PRINTFILTER_RULE_ATRACEMESSAGE"]._serialized_start = 7511 + _globals["_FTRACECONFIG_PRINTFILTER_RULE_ATRACEMESSAGE"]._serialized_end = 7556 + _globals["_FTRACECONFIG_KSYMSMEMPOLICY"]._serialized_start = 7567 + _globals["_FTRACECONFIG_KSYMSMEMPOLICY"]._serialized_end = 7651 + _globals["_GPUCOUNTERCONFIG"]._serialized_start = 7653 + _globals["_GPUCOUNTERCONFIG"]._serialized_end = 7773 + _globals["_VULKANMEMORYCONFIG"]._serialized_start = 7775 + _globals["_VULKANMEMORYCONFIG"]._serialized_end = 7865 + _globals["_INODEFILECONFIG"]._serialized_start = 7868 + _globals["_INODEFILECONFIG"]._serialized_end = 8159 + _globals["_INODEFILECONFIG_MOUNTPOINTMAPPINGENTRY"]._serialized_start = 8095 + _globals["_INODEFILECONFIG_MOUNTPOINTMAPPINGENTRY"]._serialized_end = 8159 + _globals["_CONSOLECONFIG"]._serialized_start = 8162 + _globals["_CONSOLECONFIG"]._serialized_end = 8327 + _globals["_CONSOLECONFIG_OUTPUT"]._serialized_start = 8257 + _globals["_CONSOLECONFIG_OUTPUT"]._serialized_end = 8327 + _globals["_INTERCEPTORCONFIG"]._serialized_start = 8329 + _globals["_INTERCEPTORCONFIG"]._serialized_end = 8418 + _globals["_ANDROIDPOWERCONFIG"]._serialized_start = 8421 + _globals["_ANDROIDPOWERCONFIG"]._serialized_end = 8869 + _globals["_ANDROIDPOWERCONFIG_BATTERYCOUNTERS"]._serialized_start = 8662 + _globals["_ANDROIDPOWERCONFIG_BATTERYCOUNTERS"]._serialized_end = 8869 + _globals["_PROCESSSTATSCONFIG"]._serialized_start = 8872 + _globals["_PROCESSSTATSCONFIG"]._serialized_end = 9294 + _globals["_PROCESSSTATSCONFIG_QUIRKS"]._serialized_start = 9197 + _globals["_PROCESSSTATSCONFIG_QUIRKS"]._serialized_end = 9282 + _globals["_HEAPPROFDCONFIG"]._serialized_start = 9297 + _globals["_HEAPPROFDCONFIG"]._serialized_end = 10141 + _globals["_HEAPPROFDCONFIG_CONTINUOUSDUMPCONFIG"]._serialized_start = 10064 + _globals["_HEAPPROFDCONFIG_CONTINUOUSDUMPCONFIG"]._serialized_end = 10135 + _globals["_JAVAHPROFCONFIG"]._serialized_start = 10144 + _globals["_JAVAHPROFCONFIG"]._serialized_end = 10497 + _globals["_JAVAHPROFCONFIG_CONTINUOUSDUMPCONFIG"]._serialized_start = 10393 + _globals["_JAVAHPROFCONFIG_CONTINUOUSDUMPCONFIG"]._serialized_end = 10497 + _globals["_PERFEVENTS"]._serialized_start = 10500 + _globals["_PERFEVENTS"]._serialized_end = 11595 + _globals["_PERFEVENTS_TIMEBASE"]._serialized_start = 10515 + _globals["_PERFEVENTS_TIMEBASE"]._serialized_end = 10840 + _globals["_PERFEVENTS_TRACEPOINT"]._serialized_start = 10842 + _globals["_PERFEVENTS_TRACEPOINT"]._serialized_end = 10884 + _globals["_PERFEVENTS_RAWEVENT"]._serialized_start = 10886 + _globals["_PERFEVENTS_RAWEVENT"]._serialized_end = 10960 + _globals["_PERFEVENTS_COUNTER"]._serialized_start = 10963 + _globals["_PERFEVENTS_COUNTER"]._serialized_end = 11451 + _globals["_PERFEVENTS_PERFCLOCK"]._serialized_start = 11454 + _globals["_PERFEVENTS_PERFCLOCK"]._serialized_end = 11595 + _globals["_PERFEVENTCONFIG"]._serialized_start = 11598 + _globals["_PERFEVENTCONFIG"]._serialized_end = 12581 + _globals["_PERFEVENTCONFIG_CALLSTACKSAMPLING"]._serialized_start = 12180 + _globals["_PERFEVENTCONFIG_CALLSTACKSAMPLING"]._serialized_end = 12343 + _globals["_PERFEVENTCONFIG_SCOPE"]._serialized_start = 12346 + _globals["_PERFEVENTCONFIG_SCOPE"]._serialized_end = 12506 + _globals["_PERFEVENTCONFIG_UNWINDMODE"]._serialized_start = 12508 + _globals["_PERFEVENTCONFIG_UNWINDMODE"]._serialized_end = 12575 + _globals["_STATSDTRACINGCONFIG"]._serialized_start = 12584 + _globals["_STATSDTRACINGCONFIG"]._serialized_end = 12738 + _globals["_STATSDPULLATOMCONFIG"]._serialized_start = 12741 + _globals["_STATSDPULLATOMCONFIG"]._serialized_end = 12881 + _globals["_SYSSTATSCONFIG"]._serialized_start = 12884 + _globals["_SYSSTATSCONFIG"]._serialized_end = 13504 + _globals["_SYSSTATSCONFIG_STATCOUNTERS"]._serialized_start = 13381 + _globals["_SYSSTATSCONFIG_STATCOUNTERS"]._serialized_end = 13504 + _globals["_SYSTEMINFOCONFIG"]._serialized_start = 13506 + _globals["_SYSTEMINFOCONFIG"]._serialized_end = 13524 + _globals["_TESTCONFIG"]._serialized_start = 13527 + _globals["_TESTCONFIG"]._serialized_end = 14052 + _globals["_TESTCONFIG_DUMMYFIELDS"]._serialized_start = 13729 + _globals["_TESTCONFIG_DUMMYFIELDS"]._serialized_end = 14052 + _globals["_TRACKEVENTCONFIG"]._serialized_start = 14055 + _globals["_TRACKEVENTCONFIG"]._serialized_end = 14357 + _globals["_DATASOURCECONFIG"]._serialized_start = 14360 + _globals["_DATASOURCECONFIG"]._serialized_end = 16978 + _globals["_DATASOURCECONFIG_SESSIONINITIATOR"]._serialized_start = 16874 + _globals["_DATASOURCECONFIG_SESSIONINITIATOR"]._serialized_end = 16965 + _globals["_TRACECONFIG"]._serialized_start = 16981 + _globals["_TRACECONFIG"]._serialized_end = 21566 + _globals["_TRACECONFIG_BUFFERCONFIG"]._serialized_start = 18700 + _globals["_TRACECONFIG_BUFFERCONFIG"]._serialized_end = 18934 + _globals["_TRACECONFIG_BUFFERCONFIG_FILLPOLICY"]._serialized_start = 18863 + _globals["_TRACECONFIG_BUFFERCONFIG_FILLPOLICY"]._serialized_end = 18922 + _globals["_TRACECONFIG_DATASOURCE"]._serialized_start = 18937 + _globals["_TRACECONFIG_DATASOURCE"]._serialized_end = 19066 + _globals["_TRACECONFIG_BUILTINDATASOURCE"]._serialized_start = 19069 + _globals["_TRACECONFIG_BUILTINDATASOURCE"]._serialized_end = 19388 + _globals["_TRACECONFIG_PRODUCERCONFIG"]._serialized_start = 19390 + _globals["_TRACECONFIG_PRODUCERCONFIG"]._serialized_end = 19472 + _globals["_TRACECONFIG_STATSDMETADATA"]._serialized_start = 19475 + _globals["_TRACECONFIG_STATSDMETADATA"]._serialized_end = 19617 + _globals["_TRACECONFIG_GUARDRAILOVERRIDES"]._serialized_start = 19619 + _globals["_TRACECONFIG_GUARDRAILOVERRIDES"]._serialized_end = 19713 + _globals["_TRACECONFIG_TRIGGERCONFIG"]._serialized_start = 19716 + _globals["_TRACECONFIG_TRIGGERCONFIG"]._serialized_end = 20174 + _globals["_TRACECONFIG_TRIGGERCONFIG_TRIGGER"]._serialized_start = 19950 + _globals["_TRACECONFIG_TRIGGERCONFIG_TRIGGER"]._serialized_end = 20073 + _globals["_TRACECONFIG_TRIGGERCONFIG_TRIGGERMODE"]._serialized_start = 20075 + _globals["_TRACECONFIG_TRIGGERCONFIG_TRIGGERMODE"]._serialized_end = 20168 + _globals["_TRACECONFIG_INCREMENTALSTATECONFIG"]._serialized_start = 20176 + _globals["_TRACECONFIG_INCREMENTALSTATECONFIG"]._serialized_end = 20225 + _globals["_TRACECONFIG_INCIDENTREPORTCONFIG"]._serialized_start = 20228 + _globals["_TRACECONFIG_INCIDENTREPORTCONFIG"]._serialized_end = 20379 + _globals["_TRACECONFIG_TRACEFILTER"]._serialized_start = 20382 + _globals["_TRACECONFIG_TRACEFILTER"]._serialized_end = 20979 + _globals["_TRACECONFIG_TRACEFILTER_STRINGFILTERRULE"]._serialized_start = 20526 + _globals["_TRACECONFIG_TRACEFILTER_STRINGFILTERRULE"]._serialized_end = 20680 + _globals["_TRACECONFIG_TRACEFILTER_STRINGFILTERCHAIN"]._serialized_start = 20682 + _globals["_TRACECONFIG_TRACEFILTER_STRINGFILTERCHAIN"]._serialized_end = 20775 + _globals["_TRACECONFIG_TRACEFILTER_STRINGFILTERPOLICY"]._serialized_start = 20778 + _globals["_TRACECONFIG_TRACEFILTER_STRINGFILTERPOLICY"]._serialized_end = 20979 + _globals["_TRACECONFIG_ANDROIDREPORTCONFIG"]._serialized_start = 20982 + _globals["_TRACECONFIG_ANDROIDREPORTCONFIG"]._serialized_end = 21133 + _globals["_TRACECONFIG_CMDTRACESTARTDELAY"]._serialized_start = 21135 + _globals["_TRACECONFIG_CMDTRACESTARTDELAY"]._serialized_end = 21199 + _globals["_TRACECONFIG_SESSIONSEMAPHORE"]._serialized_start = 21201 + _globals["_TRACECONFIG_SESSIONSEMAPHORE"]._serialized_end = 21266 + _globals["_TRACECONFIG_LOCKDOWNMODEOPERATION"]._serialized_start = 21268 + _globals["_TRACECONFIG_LOCKDOWNMODEOPERATION"]._serialized_end = 21353 + _globals["_TRACECONFIG_COMPRESSIONTYPE"]._serialized_start = 21355 + _globals["_TRACECONFIG_COMPRESSIONTYPE"]._serialized_end = 21436 + _globals["_TRACECONFIG_STATSDLOGGING"]._serialized_start = 21438 + _globals["_TRACECONFIG_STATSDLOGGING"]._serialized_end = 21542 + _globals["_TRACESTATS"]._serialized_start = 21569 + _globals["_TRACESTATS"]._serialized_end = 23122 + _globals["_TRACESTATS_BUFFERSTATS"]._serialized_start = 22204 + _globals["_TRACESTATS_BUFFERSTATS"]._serialized_end = 22726 + _globals["_TRACESTATS_WRITERSTATS"]._serialized_start = 22729 + _globals["_TRACESTATS_WRITERSTATS"]._serialized_end = 22864 + _globals["_TRACESTATS_FILTERSTATS"]._serialized_start = 22867 + _globals["_TRACESTATS_FILTERSTATS"]._serialized_end = 23021 + _globals["_TRACESTATS_FINALFLUSHOUTCOME"]._serialized_start = 23023 + _globals["_TRACESTATS_FINALFLUSHOUTCOME"]._serialized_end = 23122 + _globals["_ANDROIDGAMEINTERVENTIONLIST"]._serialized_start = 23125 + _globals["_ANDROIDGAMEINTERVENTIONLIST"]._serialized_end = 23524 + _globals["_ANDROIDGAMEINTERVENTIONLIST_GAMEMODEINFO"]._serialized_start = 23282 + _globals["_ANDROIDGAMEINTERVENTIONLIST_GAMEMODEINFO"]._serialized_end = 23372 + _globals["_ANDROIDGAMEINTERVENTIONLIST_GAMEPACKAGEINFO"]._serialized_start = 23375 + _globals["_ANDROIDGAMEINTERVENTIONLIST_GAMEPACKAGEINFO"]._serialized_end = 23524 + _globals["_ANDROIDLOGPACKET"]._serialized_start = 23527 + _globals["_ANDROIDLOGPACKET"]._serialized_end = 24089 + _globals["_ANDROIDLOGPACKET_LOGEVENT"]._serialized_start = 23664 + _globals["_ANDROIDLOGPACKET_LOGEVENT"]._serialized_end = 24020 + _globals["_ANDROIDLOGPACKET_LOGEVENT_ARG"]._serialized_start = 23924 + _globals["_ANDROIDLOGPACKET_LOGEVENT_ARG"]._serialized_end = 24020 + _globals["_ANDROIDLOGPACKET_STATS"]._serialized_start = 24022 + _globals["_ANDROIDLOGPACKET_STATS"]._serialized_end = 24089 + _globals["_ANDROIDSYSTEMPROPERTY"]._serialized_start = 24092 + _globals["_ANDROIDSYSTEMPROPERTY"]._serialized_end = 24231 + _globals["_ANDROIDSYSTEMPROPERTY_PROPERTYVALUE"]._serialized_start = 24187 + _globals["_ANDROIDSYSTEMPROPERTY_PROPERTYVALUE"]._serialized_end = 24231 + _globals["_ANDROIDCAMERAFRAMEEVENT"]._serialized_start = 24234 + _globals["_ANDROIDCAMERAFRAMEEVENT"]._serialized_end = 25132 + _globals[ + "_ANDROIDCAMERAFRAMEEVENT_CAMERANODEPROCESSINGDETAILS" + ]._serialized_start = 24821 + _globals["_ANDROIDCAMERAFRAMEEVENT_CAMERANODEPROCESSINGDETAILS"]._serialized_end = ( + 24954 + ) + _globals["_ANDROIDCAMERAFRAMEEVENT_CAPTURERESULTSTATUS"]._serialized_start = 24957 + _globals["_ANDROIDCAMERAFRAMEEVENT_CAPTURERESULTSTATUS"]._serialized_end = 25132 + _globals["_ANDROIDCAMERASESSIONSTATS"]._serialized_start = 25135 + _globals["_ANDROIDCAMERASESSIONSTATS"]._serialized_end = 25702 + _globals["_ANDROIDCAMERASESSIONSTATS_CAMERAGRAPH"]._serialized_start = 25256 + _globals["_ANDROIDCAMERASESSIONSTATS_CAMERAGRAPH"]._serialized_end = 25702 + _globals["_ANDROIDCAMERASESSIONSTATS_CAMERAGRAPH_CAMERANODE"]._serialized_start = ( + 25435 + ) + _globals["_ANDROIDCAMERASESSIONSTATS_CAMERAGRAPH_CAMERANODE"]._serialized_end = ( + 25553 + ) + _globals["_ANDROIDCAMERASESSIONSTATS_CAMERAGRAPH_CAMERAEDGE"]._serialized_start = ( + 25556 + ) + _globals["_ANDROIDCAMERASESSIONSTATS_CAMERAGRAPH_CAMERAEDGE"]._serialized_end = ( + 25702 + ) + _globals["_FRAMETIMELINEEVENT"]._serialized_start = 25705 + _globals["_FRAMETIMELINEEVENT"]._serialized_end = 27902 + _globals["_FRAMETIMELINEEVENT_EXPECTEDSURFACEFRAMESTART"]._serialized_start = 26198 + _globals["_FRAMETIMELINEEVENT_EXPECTEDSURFACEFRAMESTART"]._serialized_end = 26318 + _globals["_FRAMETIMELINEEVENT_ACTUALSURFACEFRAMESTART"]._serialized_start = 26321 + _globals["_FRAMETIMELINEEVENT_ACTUALSURFACEFRAMESTART"]._serialized_end = 26756 + _globals["_FRAMETIMELINEEVENT_EXPECTEDDISPLAYFRAMESTART"]._serialized_start = 26758 + _globals["_FRAMETIMELINEEVENT_EXPECTEDDISPLAYFRAMESTART"]._serialized_end = 26829 + _globals["_FRAMETIMELINEEVENT_ACTUALDISPLAYFRAMESTART"]._serialized_start = 26832 + _globals["_FRAMETIMELINEEVENT_ACTUALDISPLAYFRAMESTART"]._serialized_end = 27199 + _globals["_FRAMETIMELINEEVENT_FRAMEEND"]._serialized_start = 27201 + _globals["_FRAMETIMELINEEVENT_FRAMEEND"]._serialized_end = 27227 + _globals["_FRAMETIMELINEEVENT_JANKTYPE"]._serialized_start = 27230 + _globals["_FRAMETIMELINEEVENT_JANKTYPE"]._serialized_end = 27534 + _globals["_FRAMETIMELINEEVENT_JANKSEVERITYTYPE"]._serialized_start = 27536 + _globals["_FRAMETIMELINEEVENT_JANKSEVERITYTYPE"]._serialized_end = 27636 + _globals["_FRAMETIMELINEEVENT_PRESENTTYPE"]._serialized_start = 27639 + _globals["_FRAMETIMELINEEVENT_PRESENTTYPE"]._serialized_end = 27777 + _globals["_FRAMETIMELINEEVENT_PREDICTIONTYPE"]._serialized_start = 27779 + _globals["_FRAMETIMELINEEVENT_PREDICTIONTYPE"]._serialized_end = 27893 + _globals["_GPUMEMTOTALEVENT"]._serialized_start = 27904 + _globals["_GPUMEMTOTALEVENT"]._serialized_end = 27965 + _globals["_GRAPHICSFRAMEEVENT"]._serialized_start = 27968 + _globals["_GRAPHICSFRAMEEVENT"]._serialized_end = 28465 + _globals["_GRAPHICSFRAMEEVENT_BUFFEREVENT"]._serialized_start = 28062 + _globals["_GRAPHICSFRAMEEVENT_BUFFEREVENT"]._serialized_end = 28224 + _globals["_GRAPHICSFRAMEEVENT_BUFFEREVENTTYPE"]._serialized_start = 28227 + _globals["_GRAPHICSFRAMEEVENT_BUFFEREVENTTYPE"]._serialized_end = 28465 + _globals["_INITIALDISPLAYSTATE"]._serialized_start = 28467 + _globals["_INITIALDISPLAYSTATE"]._serialized_end = 28531 + _globals["_NETWORKPACKETEVENT"]._serialized_start = 28534 + _globals["_NETWORKPACKETEVENT"]._serialized_end = 28785 + _globals["_NETWORKPACKETBUNDLE"]._serialized_start = 28788 + _globals["_NETWORKPACKETBUNDLE"]._serialized_end = 29022 + _globals["_NETWORKPACKETCONTEXT"]._serialized_start = 29024 + _globals["_NETWORKPACKETCONTEXT"]._serialized_end = 29109 + _globals["_PACKAGESLIST"]._serialized_start = 29112 + _globals["_PACKAGESLIST"]._serialized_end = 29344 + _globals["_PACKAGESLIST_PACKAGEINFO"]._serialized_start = 29230 + _globals["_PACKAGESLIST_PACKAGEINFO"]._serialized_end = 29344 + _globals["_PIXELMODEMEVENTS"]._serialized_start = 29346 + _globals["_PIXELMODEMEVENTS"]._serialized_end = 29406 + _globals["_PIXELMODEMTOKENDATABASE"]._serialized_start = 29408 + _globals["_PIXELMODEMTOKENDATABASE"]._serialized_end = 29451 + _globals["_PROTOLOGMESSAGE"]._serialized_start = 29454 + _globals["_PROTOLOGMESSAGE"]._serialized_end = 29609 + _globals["_PROTOLOGVIEWERCONFIG"]._serialized_start = 29612 + _globals["_PROTOLOGVIEWERCONFIG"]._serialized_end = 29948 + _globals["_PROTOLOGVIEWERCONFIG_MESSAGEDATA"]._serialized_start = 29767 + _globals["_PROTOLOGVIEWERCONFIG_MESSAGEDATA"]._serialized_end = 29900 + _globals["_PROTOLOGVIEWERCONFIG_GROUP"]._serialized_start = 29902 + _globals["_PROTOLOGVIEWERCONFIG_GROUP"]._serialized_end = 29948 + _globals["_SHELLTRANSITION"]._serialized_start = 29951 + _globals["_SHELLTRANSITION"]._serialized_end = 30488 + _globals["_SHELLTRANSITION_TARGET"]._serialized_start = 30414 + _globals["_SHELLTRANSITION_TARGET"]._serialized_end = 30488 + _globals["_SHELLHANDLERMAPPINGS"]._serialized_start = 30490 + _globals["_SHELLHANDLERMAPPINGS"]._serialized_end = 30567 + _globals["_SHELLHANDLERMAPPING"]._serialized_start = 30569 + _globals["_SHELLHANDLERMAPPING"]._serialized_end = 30616 + _globals["_RECTPROTO"]._serialized_start = 30618 + _globals["_RECTPROTO"]._serialized_end = 30687 + _globals["_REGIONPROTO"]._serialized_start = 30689 + _globals["_REGIONPROTO"]._serialized_end = 30750 + _globals["_SIZEPROTO"]._serialized_start = 30752 + _globals["_SIZEPROTO"]._serialized_end = 30785 + _globals["_TRANSFORMPROTO"]._serialized_start = 30787 + _globals["_TRANSFORMPROTO"]._serialized_end = 30873 + _globals["_COLORPROTO"]._serialized_start = 30875 + _globals["_COLORPROTO"]._serialized_end = 30931 + _globals["_INPUTWINDOWINFOPROTO"]._serialized_start = 30934 + _globals["_INPUTWINDOWINFOPROTO"]._serialized_end = 31509 + _globals["_BLURREGION"]._serialized_start = 31512 + _globals["_BLURREGION"]._serialized_end = 31722 + _globals["_COLORTRANSFORMPROTO"]._serialized_start = 31724 + _globals["_COLORTRANSFORMPROTO"]._serialized_end = 31762 + _globals["_LAYERSTRACEFILEPROTO"]._serialized_start = 31765 + _globals["_LAYERSTRACEFILEPROTO"]._serialized_end = 31981 + _globals["_LAYERSTRACEFILEPROTO_MAGICNUMBER"]._serialized_start = 31907 + _globals["_LAYERSTRACEFILEPROTO_MAGICNUMBER"]._serialized_end = 31981 + _globals["_LAYERSSNAPSHOTPROTO"]._serialized_start = 31984 + _globals["_LAYERSSNAPSHOTPROTO"]._serialized_end = 32243 + _globals["_LAYERSPROTO"]._serialized_start = 32245 + _globals["_LAYERSPROTO"]._serialized_end = 32303 + _globals["_DISPLAYPROTO"]._serialized_start = 32306 + _globals["_DISPLAYPROTO"]._serialized_end = 32571 + _globals["_LAYERPROTO"]._serialized_start = 32574 + _globals["_LAYERPROTO"]._serialized_end = 34888 + _globals["_LAYERPROTO_METADATAENTRY"]._serialized_start = 34841 + _globals["_LAYERPROTO_METADATAENTRY"]._serialized_end = 34888 + _globals["_POSITIONPROTO"]._serialized_start = 34890 + _globals["_POSITIONPROTO"]._serialized_end = 34927 + _globals["_FLOATRECTPROTO"]._serialized_start = 34929 + _globals["_FLOATRECTPROTO"]._serialized_end = 35003 + _globals["_ACTIVEBUFFERPROTO"]._serialized_start = 35005 + _globals["_ACTIVEBUFFERPROTO"]._serialized_end = 35102 + _globals["_BARRIERLAYERPROTO"]._serialized_start = 35104 + _globals["_BARRIERLAYERPROTO"]._serialized_end = 35157 + _globals["_TRANSACTIONTRACEFILE"]._serialized_start = 35160 + _globals["_TRANSACTIONTRACEFILE"]._serialized_end = 35395 + _globals["_TRANSACTIONTRACEFILE_MAGICNUMBER"]._serialized_start = 35321 + _globals["_TRANSACTIONTRACEFILE_MAGICNUMBER"]._serialized_end = 35395 + _globals["_TRANSACTIONTRACEENTRY"]._serialized_start = 35398 + _globals["_TRANSACTIONTRACEENTRY"]._serialized_end = 35800 + _globals["_DISPLAYINFO"]._serialized_start = 35803 + _globals["_DISPLAYINFO"]._serialized_end = 36137 + _globals["_LAYERCREATIONARGS"]._serialized_start = 36140 + _globals["_LAYERCREATIONARGS"]._serialized_end = 36301 + _globals["_TRANSFORM"]._serialized_start = 36303 + _globals["_TRANSFORM"]._serialized_end = 36394 + _globals["_TRANSACTIONSTATE"]._serialized_start = 36397 + _globals["_TRANSACTIONSTATE"]._serialized_end = 36666 + _globals["_LAYERSTATE"]._serialized_start = 36669 + _globals["_LAYERSTATE"]._serialized_end = 40829 + _globals["_LAYERSTATE_MATRIX22"]._serialized_start = 38050 + _globals["_LAYERSTATE_MATRIX22"]._serialized_end = 38116 + _globals["_LAYERSTATE_COLOR3"]._serialized_start = 38118 + _globals["_LAYERSTATE_COLOR3"]._serialized_end = 38159 + _globals["_LAYERSTATE_BUFFERDATA"]._serialized_start = 38162 + _globals["_LAYERSTATE_BUFFERDATA"]._serialized_end = 38950 + _globals["_LAYERSTATE_BUFFERDATA_BUFFERDATACHANGE"]._serialized_start = 38378 + _globals["_LAYERSTATE_BUFFERDATA_BUFFERDATACHANGE"]._serialized_end = 38489 + _globals["_LAYERSTATE_BUFFERDATA_PIXELFORMAT"]._serialized_start = 38492 + _globals["_LAYERSTATE_BUFFERDATA_PIXELFORMAT"]._serialized_end = 38950 + _globals["_LAYERSTATE_WINDOWINFO"]._serialized_start = 38953 + _globals["_LAYERSTATE_WINDOWINFO"]._serialized_end = 39367 + _globals["_LAYERSTATE_CHANGESLSB"]._serialized_start = 39370 + _globals["_LAYERSTATE_CHANGESLSB"]._serialized_end = 40130 + _globals["_LAYERSTATE_CHANGESMSB"]._serialized_start = 40133 + _globals["_LAYERSTATE_CHANGESMSB"]._serialized_end = 40614 + _globals["_LAYERSTATE_FLAGS"]._serialized_start = 40617 + _globals["_LAYERSTATE_FLAGS"]._serialized_end = 40779 + _globals["_LAYERSTATE_DROPINPUTMODE"]._serialized_start = 40781 + _globals["_LAYERSTATE_DROPINPUTMODE"]._serialized_end = 40829 + _globals["_DISPLAYSTATE"]._serialized_start = 40832 + _globals["_DISPLAYSTATE"]._serialized_end = 41235 + _globals["_DISPLAYSTATE_CHANGES"]._serialized_start = 41088 + _globals["_DISPLAYSTATE_CHANGES"]._serialized_end = 41235 + _globals["_WINSCOPEEXTENSIONS"]._serialized_start = 41237 + _globals["_WINSCOPEEXTENSIONS"]._serialized_end = 41263 + _globals["_CHROMEBENCHMARKMETADATA"]._serialized_start = 41266 + _globals["_CHROMEBENCHMARKMETADATA"]._serialized_end = 41508 + _globals["_CHROMEMETADATAPACKET"]._serialized_start = 41511 + _globals["_CHROMEMETADATAPACKET"]._serialized_end = 41790 + _globals["_CHROMEMETADATAPACKET_FINCHHASH"]._serialized_start = 41750 + _globals["_CHROMEMETADATAPACKET_FINCHHASH"]._serialized_end = 41790 + _globals["_BACKGROUNDTRACINGMETADATA"]._serialized_start = 41793 + _globals["_BACKGROUNDTRACINGMETADATA"]._serialized_end = 42838 + _globals["_BACKGROUNDTRACINGMETADATA_TRIGGERRULE"]._serialized_start = 42009 + _globals["_BACKGROUNDTRACINGMETADATA_TRIGGERRULE"]._serialized_end = 42838 + _globals[ + "_BACKGROUNDTRACINGMETADATA_TRIGGERRULE_HISTOGRAMRULE" + ]._serialized_start = 42313 + _globals["_BACKGROUNDTRACINGMETADATA_TRIGGERRULE_HISTOGRAMRULE"]._serialized_end = ( + 42419 + ) + _globals["_BACKGROUNDTRACINGMETADATA_TRIGGERRULE_NAMEDRULE"]._serialized_start = ( + 42422 + ) + _globals["_BACKGROUNDTRACINGMETADATA_TRIGGERRULE_NAMEDRULE"]._serialized_end = 42700 + _globals[ + "_BACKGROUNDTRACINGMETADATA_TRIGGERRULE_NAMEDRULE_EVENTTYPE" + ]._serialized_start = 42567 + _globals[ + "_BACKGROUNDTRACINGMETADATA_TRIGGERRULE_NAMEDRULE_EVENTTYPE" + ]._serialized_end = 42700 + _globals["_BACKGROUNDTRACINGMETADATA_TRIGGERRULE_TRIGGERTYPE"]._serialized_start = ( + 42703 + ) + _globals["_BACKGROUNDTRACINGMETADATA_TRIGGERRULE_TRIGGERTYPE"]._serialized_end = ( + 42838 + ) + _globals["_CHROMETRACEDVALUE"]._serialized_start = 42841 + _globals["_CHROMETRACEDVALUE"]._serialized_end = 43180 + _globals["_CHROMETRACEDVALUE_NESTEDTYPE"]._serialized_start = 43147 + _globals["_CHROMETRACEDVALUE_NESTEDTYPE"]._serialized_end = 43180 + _globals["_CHROMESTRINGTABLEENTRY"]._serialized_start = 43182 + _globals["_CHROMESTRINGTABLEENTRY"]._serialized_end = 43236 + _globals["_CHROMETRACEEVENT"]._serialized_start = 43239 + _globals["_CHROMETRACEEVENT"]._serialized_end = 43880 + _globals["_CHROMETRACEEVENT_ARG"]._serialized_start = 43612 + _globals["_CHROMETRACEEVENT_ARG"]._serialized_end = 43880 + _globals["_CHROMEMETADATA"]._serialized_start = 43883 + _globals["_CHROMEMETADATA"]._serialized_end = 44011 + _globals["_CHROMELEGACYJSONTRACE"]._serialized_start = 44014 + _globals["_CHROMELEGACYJSONTRACE"]._serialized_end = 44162 + _globals["_CHROMELEGACYJSONTRACE_TRACETYPE"]._serialized_start = 44117 + _globals["_CHROMELEGACYJSONTRACE_TRACETYPE"]._serialized_end = 44162 + _globals["_CHROMEEVENTBUNDLE"]._serialized_start = 44165 + _globals["_CHROMEEVENTBUNDLE"]._serialized_end = 44460 + _globals["_CHROMETRIGGER"]._serialized_start = 44462 + _globals["_CHROMETRIGGER"]._serialized_end = 44526 + _globals["_V8STRING"]._serialized_start = 44528 + _globals["_V8STRING"]._serialized_end = 44614 + _globals["_INTERNEDV8STRING"]._serialized_start = 44616 + _globals["_INTERNEDV8STRING"]._serialized_end = 44723 + _globals["_INTERNEDV8JSSCRIPT"]._serialized_start = 44726 + _globals["_INTERNEDV8JSSCRIPT"]._serialized_end = 45051 + _globals["_INTERNEDV8JSSCRIPT_TYPE"]._serialized_start = 44921 + _globals["_INTERNEDV8JSSCRIPT_TYPE"]._serialized_end = 45051 + _globals["_INTERNEDV8WASMSCRIPT"]._serialized_start = 45053 + _globals["_INTERNEDV8WASMSCRIPT"]._serialized_end = 45120 + _globals["_INTERNEDV8JSFUNCTION"]._serialized_start = 45123 + _globals["_INTERNEDV8JSFUNCTION"]._serialized_end = 46202 + _globals["_INTERNEDV8JSFUNCTION_KIND"]._serialized_start = 45320 + _globals["_INTERNEDV8JSFUNCTION_KIND"]._serialized_end = 46202 + _globals["_INTERNEDV8ISOLATE"]._serialized_start = 46205 + _globals["_INTERNEDV8ISOLATE"]._serialized_end = 46532 + _globals["_INTERNEDV8ISOLATE_CODERANGE"]._serialized_start = 46413 + _globals["_INTERNEDV8ISOLATE_CODERANGE"]._serialized_end = 46532 + _globals["_V8JSCODE"]._serialized_start = 46535 + _globals["_V8JSCODE"]._serialized_end = 46897 + _globals["_V8JSCODE_TIER"]._serialized_start = 46761 + _globals["_V8JSCODE_TIER"]._serialized_end = 46881 + _globals["_V8INTERNALCODE"]._serialized_start = 46900 + _globals["_V8INTERNALCODE"]._serialized_end = 47381 + _globals["_V8INTERNALCODE_TYPE"]._serialized_start = 47123 + _globals["_V8INTERNALCODE_TYPE"]._serialized_end = 47381 + _globals["_V8WASMCODE"]._serialized_start = 47384 + _globals["_V8WASMCODE"]._serialized_end = 47707 + _globals["_V8WASMCODE_TIER"]._serialized_start = 47646 + _globals["_V8WASMCODE_TIER"]._serialized_end = 47707 + _globals["_V8REGEXPCODE"]._serialized_start = 47710 + _globals["_V8REGEXPCODE"]._serialized_end = 47886 + _globals["_V8CODEMOVE"]._serialized_start = 47889 + _globals["_V8CODEMOVE"]._serialized_end = 48114 + _globals["_V8CODEDEFAULTS"]._serialized_start = 48116 + _globals["_V8CODEDEFAULTS"]._serialized_end = 48145 + _globals["_CLOCKSNAPSHOT"]._serialized_start = 48148 + _globals["_CLOCKSNAPSHOT"]._serialized_end = 48550 + _globals["_CLOCKSNAPSHOT_CLOCK"]._serialized_start = 48280 + _globals["_CLOCKSNAPSHOT_CLOCK"]._serialized_end = 48550 + _globals["_CLOCKSNAPSHOT_CLOCK_BUILTINCLOCKS"]._serialized_start = 48379 + _globals["_CLOCKSNAPSHOT_CLOCK_BUILTINCLOCKS"]._serialized_end = 48550 + _globals["_CSWITCHETWEVENT"]._serialized_start = 48553 + _globals["_CSWITCHETWEVENT"]._serialized_end = 49953 + _globals["_CSWITCHETWEVENT_OLDTHREADWAITREASON"]._serialized_start = 49017 + _globals["_CSWITCHETWEVENT_OLDTHREADWAITREASON"]._serialized_end = 49762 + _globals["_CSWITCHETWEVENT_OLDTHREADWAITMODE"]._serialized_start = 49764 + _globals["_CSWITCHETWEVENT_OLDTHREADWAITMODE"]._serialized_end = 49815 + _globals["_CSWITCHETWEVENT_OLDTHREADSTATE"]._serialized_start = 49818 + _globals["_CSWITCHETWEVENT_OLDTHREADSTATE"]._serialized_end = 49953 + _globals["_READYTHREADETWEVENT"]._serialized_start = 49956 + _globals["_READYTHREADETWEVENT"]._serialized_end = 50374 + _globals["_READYTHREADETWEVENT_ADJUSTREASON"]._serialized_start = 50162 + _globals["_READYTHREADETWEVENT_ADJUSTREASON"]._serialized_end = 50250 + _globals["_READYTHREADETWEVENT_TRACEFLAG"]._serialized_start = 50252 + _globals["_READYTHREADETWEVENT_TRACEFLAG"]._serialized_end = 50374 + _globals["_ETWTRACEEVENT"]._serialized_start = 50377 + _globals["_ETWTRACEEVENT"]._serialized_end = 50549 + _globals["_ETWTRACEEVENTBUNDLE"]._serialized_start = 50551 + _globals["_ETWTRACEEVENTBUNDLE"]._serialized_end = 50632 + _globals["_FILEDESCRIPTORSET"]._serialized_start = 50634 + _globals["_FILEDESCRIPTORSET"]._serialized_end = 50705 + _globals["_FILEDESCRIPTORPROTO"]._serialized_start = 50708 + _globals["_FILEDESCRIPTORPROTO"]._serialized_end = 51027 + _globals["_DESCRIPTORPROTO"]._serialized_start = 51030 + _globals["_DESCRIPTORPROTO"]._serialized_end = 51496 + _globals["_DESCRIPTORPROTO_RESERVEDRANGE"]._serialized_start = 51441 + _globals["_DESCRIPTORPROTO_RESERVEDRANGE"]._serialized_end = 51484 + _globals["_UNINTERPRETEDOPTION"]._serialized_start = 51499 + _globals["_UNINTERPRETEDOPTION"]._serialized_end = 51785 + _globals["_UNINTERPRETEDOPTION_NAMEPART"]._serialized_start = 51734 + _globals["_UNINTERPRETEDOPTION_NAMEPART"]._serialized_end = 51785 + _globals["_FIELDOPTIONS"]._serialized_start = 51787 + _globals["_FIELDOPTIONS"]._serialized_end = 51886 + _globals["_FIELDDESCRIPTORPROTO"]._serialized_start = 51889 + _globals["_FIELDDESCRIPTORPROTO"]._serialized_end = 52576 + _globals["_FIELDDESCRIPTORPROTO_TYPE"]._serialized_start = 52191 + _globals["_FIELDDESCRIPTORPROTO_TYPE"]._serialized_end = 52501 + _globals["_FIELDDESCRIPTORPROTO_LABEL"]._serialized_start = 52503 + _globals["_FIELDDESCRIPTORPROTO_LABEL"]._serialized_end = 52570 + _globals["_ONEOFDESCRIPTORPROTO"]._serialized_start = 52578 + _globals["_ONEOFDESCRIPTORPROTO"]._serialized_end = 52662 + _globals["_ENUMDESCRIPTORPROTO"]._serialized_start = 52665 + _globals["_ENUMDESCRIPTORPROTO"]._serialized_end = 52793 + _globals["_ENUMVALUEDESCRIPTORPROTO"]._serialized_start = 52795 + _globals["_ENUMVALUEDESCRIPTORPROTO"]._serialized_end = 52857 + _globals["_ONEOFOPTIONS"]._serialized_start = 52859 + _globals["_ONEOFOPTIONS"]._serialized_end = 52892 + _globals["_EXTENSIONDESCRIPTOR"]._serialized_start = 52894 + _globals["_EXTENSIONDESCRIPTOR"]._serialized_end = 52974 + _globals["_INODEFILEMAP"]._serialized_start = 52977 + _globals["_INODEFILEMAP"]._serialized_end = 53241 + _globals["_INODEFILEMAP_ENTRY"]._serialized_start = 53095 + _globals["_INODEFILEMAP_ENTRY"]._serialized_end = 53241 + _globals["_INODEFILEMAP_ENTRY_TYPE"]._serialized_start = 53197 + _globals["_INODEFILEMAP_ENTRY_TYPE"]._serialized_end = 53241 + _globals["_ANDROIDFSDATAREADENDFTRACEEVENT"]._serialized_start = 53243 + _globals["_ANDROIDFSDATAREADENDFTRACEEVENT"]._serialized_end = 53320 + _globals["_ANDROIDFSDATAREADSTARTFTRACEEVENT"]._serialized_start = 53323 + _globals["_ANDROIDFSDATAREADSTARTFTRACEEVENT"]._serialized_end = 53465 + _globals["_ANDROIDFSDATAWRITEENDFTRACEEVENT"]._serialized_start = 53467 + _globals["_ANDROIDFSDATAWRITEENDFTRACEEVENT"]._serialized_end = 53545 + _globals["_ANDROIDFSDATAWRITESTARTFTRACEEVENT"]._serialized_start = 53548 + _globals["_ANDROIDFSDATAWRITESTARTFTRACEEVENT"]._serialized_end = 53691 + _globals["_ANDROIDFSFSYNCENDFTRACEEVENT"]._serialized_start = 53693 + _globals["_ANDROIDFSFSYNCENDFTRACEEVENT"]._serialized_end = 53767 + _globals["_ANDROIDFSFSYNCSTARTFTRACEEVENT"]._serialized_start = 53769 + _globals["_ANDROIDFSFSYNCSTARTFTRACEEVENT"]._serialized_end = 53877 + _globals["_BCLIRQTRIGGERFTRACEEVENT"]._serialized_start = 53880 + _globals["_BCLIRQTRIGGERFTRACEEVENT"]._serialized_end = 54069 + _globals["_BINDERTRANSACTIONFTRACEEVENT"]._serialized_start = 54072 + _globals["_BINDERTRANSACTIONFTRACEEVENT"]._serialized_end = 54221 + _globals["_BINDERTRANSACTIONRECEIVEDFTRACEEVENT"]._serialized_start = 54223 + _globals["_BINDERTRANSACTIONRECEIVEDFTRACEEVENT"]._serialized_end = 54279 + _globals["_BINDERSETPRIORITYFTRACEEVENT"]._serialized_start = 54281 + _globals["_BINDERSETPRIORITYFTRACEEVENT"]._serialized_end = 54399 + _globals["_BINDERLOCKFTRACEEVENT"]._serialized_start = 54401 + _globals["_BINDERLOCKFTRACEEVENT"]._serialized_end = 54437 + _globals["_BINDERLOCKEDFTRACEEVENT"]._serialized_start = 54439 + _globals["_BINDERLOCKEDFTRACEEVENT"]._serialized_end = 54477 + _globals["_BINDERUNLOCKFTRACEEVENT"]._serialized_start = 54479 + _globals["_BINDERUNLOCKFTRACEEVENT"]._serialized_end = 54517 + _globals["_BINDERTRANSACTIONALLOCBUFFTRACEEVENT"]._serialized_start = 54519 + _globals["_BINDERTRANSACTIONALLOCBUFFTRACEEVENT"]._serialized_end = 54644 + _globals["_BINDERCOMMANDFTRACEEVENT"]._serialized_start = 54646 + _globals["_BINDERCOMMANDFTRACEEVENT"]._serialized_end = 54685 + _globals["_BINDERRETURNFTRACEEVENT"]._serialized_start = 54687 + _globals["_BINDERRETURNFTRACEEVENT"]._serialized_end = 54725 + _globals["_BLOCKRQISSUEFTRACEEVENT"]._serialized_start = 54728 + _globals["_BLOCKRQISSUEFTRACEEVENT"]._serialized_end = 54857 + _globals["_BLOCKBIOBACKMERGEFTRACEEVENT"]._serialized_start = 54859 + _globals["_BLOCKBIOBACKMERGEFTRACEEVENT"]._serialized_end = 54965 + _globals["_BLOCKBIOBOUNCEFTRACEEVENT"]._serialized_start = 54967 + _globals["_BLOCKBIOBOUNCEFTRACEEVENT"]._serialized_end = 55070 + _globals["_BLOCKBIOCOMPLETEFTRACEEVENT"]._serialized_start = 55072 + _globals["_BLOCKBIOCOMPLETEFTRACEEVENT"]._serialized_end = 55178 + _globals["_BLOCKBIOFRONTMERGEFTRACEEVENT"]._serialized_start = 55180 + _globals["_BLOCKBIOFRONTMERGEFTRACEEVENT"]._serialized_end = 55287 + _globals["_BLOCKBIOQUEUEFTRACEEVENT"]._serialized_start = 55289 + _globals["_BLOCKBIOQUEUEFTRACEEVENT"]._serialized_end = 55391 + _globals["_BLOCKBIOREMAPFTRACEEVENT"]._serialized_start = 55393 + _globals["_BLOCKBIOREMAPFTRACEEVENT"]._serialized_end = 55518 + _globals["_BLOCKDIRTYBUFFERFTRACEEVENT"]._serialized_start = 55520 + _globals["_BLOCKDIRTYBUFFERFTRACEEVENT"]._serialized_end = 55592 + _globals["_BLOCKGETRQFTRACEEVENT"]._serialized_start = 55594 + _globals["_BLOCKGETRQFTRACEEVENT"]._serialized_end = 55693 + _globals["_BLOCKPLUGFTRACEEVENT"]._serialized_start = 55695 + _globals["_BLOCKPLUGFTRACEEVENT"]._serialized_end = 55731 + _globals["_BLOCKRQABORTFTRACEEVENT"]._serialized_start = 55733 + _globals["_BLOCKRQABORTFTRACEEVENT"]._serialized_end = 55849 + _globals["_BLOCKRQCOMPLETEFTRACEEVENT"]._serialized_start = 55852 + _globals["_BLOCKRQCOMPLETEFTRACEEVENT"]._serialized_end = 55986 + _globals["_BLOCKRQINSERTFTRACEEVENT"]._serialized_start = 55989 + _globals["_BLOCKRQINSERTFTRACEEVENT"]._serialized_end = 56119 + _globals["_BLOCKRQREMAPFTRACEEVENT"]._serialized_start = 56122 + _globals["_BLOCKRQREMAPFTRACEEVENT"]._serialized_end = 56263 + _globals["_BLOCKRQREQUEUEFTRACEEVENT"]._serialized_start = 56265 + _globals["_BLOCKRQREQUEUEFTRACEEVENT"]._serialized_end = 56383 + _globals["_BLOCKSLEEPRQFTRACEEVENT"]._serialized_start = 56385 + _globals["_BLOCKSLEEPRQFTRACEEVENT"]._serialized_end = 56486 + _globals["_BLOCKSPLITFTRACEEVENT"]._serialized_start = 56488 + _globals["_BLOCKSPLITFTRACEEVENT"]._serialized_end = 56588 + _globals["_BLOCKTOUCHBUFFERFTRACEEVENT"]._serialized_start = 56590 + _globals["_BLOCKTOUCHBUFFERFTRACEEVENT"]._serialized_end = 56662 + _globals["_BLOCKUNPLUGFTRACEEVENT"]._serialized_start = 56664 + _globals["_BLOCKUNPLUGFTRACEEVENT"]._serialized_end = 56717 + _globals["_CGROUPATTACHTASKFTRACEEVENT"]._serialized_start = 56720 + _globals["_CGROUPATTACHTASKFTRACEEVENT"]._serialized_end = 56862 + _globals["_CGROUPMKDIRFTRACEEVENT"]._serialized_start = 56864 + _globals["_CGROUPMKDIRFTRACEEVENT"]._serialized_end = 56958 + _globals["_CGROUPREMOUNTFTRACEEVENT"]._serialized_start = 56960 + _globals["_CGROUPREMOUNTFTRACEEVENT"]._serialized_end = 57031 + _globals["_CGROUPRMDIRFTRACEEVENT"]._serialized_start = 57033 + _globals["_CGROUPRMDIRFTRACEEVENT"]._serialized_end = 57127 + _globals["_CGROUPTRANSFERTASKSFTRACEEVENT"]._serialized_start = 57130 + _globals["_CGROUPTRANSFERTASKSFTRACEEVENT"]._serialized_end = 57275 + _globals["_CGROUPDESTROYROOTFTRACEEVENT"]._serialized_start = 57277 + _globals["_CGROUPDESTROYROOTFTRACEEVENT"]._serialized_end = 57352 + _globals["_CGROUPRELEASEFTRACEEVENT"]._serialized_start = 57354 + _globals["_CGROUPRELEASEFTRACEEVENT"]._serialized_end = 57450 + _globals["_CGROUPRENAMEFTRACEEVENT"]._serialized_start = 57452 + _globals["_CGROUPRENAMEFTRACEEVENT"]._serialized_end = 57547 + _globals["_CGROUPSETUPROOTFTRACEEVENT"]._serialized_start = 57549 + _globals["_CGROUPSETUPROOTFTRACEEVENT"]._serialized_end = 57622 + _globals["_CLKENABLEFTRACEEVENT"]._serialized_start = 57624 + _globals["_CLKENABLEFTRACEEVENT"]._serialized_end = 57660 + _globals["_CLKDISABLEFTRACEEVENT"]._serialized_start = 57662 + _globals["_CLKDISABLEFTRACEEVENT"]._serialized_end = 57699 + _globals["_CLKSETRATEFTRACEEVENT"]._serialized_start = 57701 + _globals["_CLKSETRATEFTRACEEVENT"]._serialized_end = 57752 + _globals["_CMAALLOCSTARTFTRACEEVENT"]._serialized_start = 57754 + _globals["_CMAALLOCSTARTFTRACEEVENT"]._serialized_end = 57824 + _globals["_CMAALLOCINFOFTRACEEVENT"]._serialized_start = 57827 + _globals["_CMAALLOCINFOFTRACEEVENT"]._serialized_end = 58023 + _globals["_MMCOMPACTIONBEGINFTRACEEVENT"]._serialized_start = 58025 + _globals["_MMCOMPACTIONBEGINFTRACEEVENT"]._serialized_end = 58146 + _globals["_MMCOMPACTIONDEFERCOMPACTIONFTRACEEVENT"]._serialized_start = 58149 + _globals["_MMCOMPACTIONDEFERCOMPACTIONFTRACEEVENT"]._serialized_end = 58293 + _globals["_MMCOMPACTIONDEFERREDFTRACEEVENT"]._serialized_start = 58296 + _globals["_MMCOMPACTIONDEFERREDFTRACEEVENT"]._serialized_end = 58433 + _globals["_MMCOMPACTIONDEFERRESETFTRACEEVENT"]._serialized_start = 58436 + _globals["_MMCOMPACTIONDEFERRESETFTRACEEVENT"]._serialized_end = 58575 + _globals["_MMCOMPACTIONENDFTRACEEVENT"]._serialized_start = 58578 + _globals["_MMCOMPACTIONENDFTRACEEVENT"]._serialized_end = 58713 + _globals["_MMCOMPACTIONFINISHEDFTRACEEVENT"]._serialized_start = 58715 + _globals["_MMCOMPACTIONFINISHEDFTRACEEVENT"]._serialized_end = 58802 + _globals["_MMCOMPACTIONISOLATEFREEPAGESFTRACEEVENT"]._serialized_start = 58804 + _globals["_MMCOMPACTIONISOLATEFREEPAGESFTRACEEVENT"]._serialized_end = 58919 + _globals["_MMCOMPACTIONISOLATEMIGRATEPAGESFTRACEEVENT"]._serialized_start = 58921 + _globals["_MMCOMPACTIONISOLATEMIGRATEPAGESFTRACEEVENT"]._serialized_end = 59039 + _globals["_MMCOMPACTIONKCOMPACTDSLEEPFTRACEEVENT"]._serialized_start = 59041 + _globals["_MMCOMPACTIONKCOMPACTDSLEEPFTRACEEVENT"]._serialized_end = 59093 + _globals["_MMCOMPACTIONKCOMPACTDWAKEFTRACEEVENT"]._serialized_start = 59095 + _globals["_MMCOMPACTIONKCOMPACTDWAKEFTRACEEVENT"]._serialized_end = 59209 + _globals["_MMCOMPACTIONMIGRATEPAGESFTRACEEVENT"]._serialized_start = 59211 + _globals["_MMCOMPACTIONMIGRATEPAGESFTRACEEVENT"]._serialized_end = 59288 + _globals["_MMCOMPACTIONSUITABLEFTRACEEVENT"]._serialized_start = 59290 + _globals["_MMCOMPACTIONSUITABLEFTRACEEVENT"]._serialized_end = 59377 + _globals["_MMCOMPACTIONTRYTOCOMPACTPAGESFTRACEEVENT"]._serialized_start = 59379 + _globals["_MMCOMPACTIONTRYTOCOMPACTPAGESFTRACEEVENT"]._serialized_end = 59482 + _globals["_MMCOMPACTIONWAKEUPKCOMPACTDFTRACEEVENT"]._serialized_start = 59484 + _globals["_MMCOMPACTIONWAKEUPKCOMPACTDFTRACEEVENT"]._serialized_end = 59600 + _globals["_CPUHPEXITFTRACEEVENT"]._serialized_start = 59602 + _globals["_CPUHPEXITFTRACEEVENT"]._serialized_end = 59678 + _globals["_CPUHPMULTIENTERFTRACEEVENT"]._serialized_start = 59680 + _globals["_CPUHPMULTIENTERFTRACEEVENT"]._serialized_end = 59763 + _globals["_CPUHPENTERFTRACEEVENT"]._serialized_start = 59765 + _globals["_CPUHPENTERFTRACEEVENT"]._serialized_end = 59843 + _globals["_CPUHPLATENCYFTRACEEVENT"]._serialized_start = 59845 + _globals["_CPUHPLATENCYFTRACEEVENT"]._serialized_end = 59925 + _globals["_CPUHPPAUSEFTRACEEVENT"]._serialized_start = 59927 + _globals["_CPUHPPAUSEFTRACEEVENT"]._serialized_end = 60014 + _globals["_CROSECSENSORHUBDATAFTRACEEVENT"]._serialized_start = 60017 + _globals["_CROSECSENSORHUBDATAFTRACEEVENT"]._serialized_end = 60187 + _globals["_DCVSHFREQFTRACEEVENT"]._serialized_start = 60189 + _globals["_DCVSHFREQFTRACEEVENT"]._serialized_end = 60238 + _globals["_DMAFENCEINITFTRACEEVENT"]._serialized_start = 60240 + _globals["_DMAFENCEINITFTRACEEVENT"]._serialized_end = 60331 + _globals["_DMAFENCEEMITFTRACEEVENT"]._serialized_start = 60333 + _globals["_DMAFENCEEMITFTRACEEVENT"]._serialized_end = 60424 + _globals["_DMAFENCESIGNALEDFTRACEEVENT"]._serialized_start = 60426 + _globals["_DMAFENCESIGNALEDFTRACEEVENT"]._serialized_end = 60521 + _globals["_DMAFENCEWAITSTARTFTRACEEVENT"]._serialized_start = 60523 + _globals["_DMAFENCEWAITSTARTFTRACEEVENT"]._serialized_end = 60619 + _globals["_DMAFENCEWAITENDFTRACEEVENT"]._serialized_start = 60621 + _globals["_DMAFENCEWAITENDFTRACEEVENT"]._serialized_end = 60715 + _globals["_DMAHEAPSTATFTRACEEVENT"]._serialized_start = 60717 + _globals["_DMAHEAPSTATFTRACEEVENT"]._serialized_end = 60794 + _globals["_DPUTRACINGMARKWRITEFTRACEEVENT"]._serialized_start = 60797 + _globals["_DPUTRACINGMARKWRITEFTRACEEVENT"]._serialized_end = 60926 + _globals["_DPUDSICMDFIFOSTATUSFTRACEEVENT"]._serialized_start = 60928 + _globals["_DPUDSICMDFIFOSTATUSFTRACEEVENT"]._serialized_end = 60993 + _globals["_DPUDSIRXFTRACEEVENT"]._serialized_start = 60995 + _globals["_DPUDSIRXFTRACEEVENT"]._serialized_end = 61045 + _globals["_DPUDSITXFTRACEEVENT"]._serialized_start = 61047 + _globals["_DPUDSITXFTRACEEVENT"]._serialized_end = 61130 + _globals["_DRMVBLANKEVENTFTRACEEVENT"]._serialized_start = 61132 + _globals["_DRMVBLANKEVENTFTRACEEVENT"]._serialized_end = 61219 + _globals["_DRMVBLANKEVENTDELIVEREDFTRACEEVENT"]._serialized_start = 61221 + _globals["_DRMVBLANKEVENTDELIVEREDFTRACEEVENT"]._serialized_end = 61298 + _globals["_EXT4DAWRITEBEGINFTRACEEVENT"]._serialized_start = 61300 + _globals["_EXT4DAWRITEBEGINFTRACEEVENT"]._serialized_end = 61396 + _globals["_EXT4DAWRITEENDFTRACEEVENT"]._serialized_start = 61398 + _globals["_EXT4DAWRITEENDFTRACEEVENT"]._serialized_end = 61493 + _globals["_EXT4SYNCFILEENTERFTRACEEVENT"]._serialized_start = 61495 + _globals["_EXT4SYNCFILEENTERFTRACEEVENT"]._serialized_end = 61585 + _globals["_EXT4SYNCFILEEXITFTRACEEVENT"]._serialized_start = 61587 + _globals["_EXT4SYNCFILEEXITFTRACEEVENT"]._serialized_end = 61655 + _globals["_EXT4ALLOCDABLOCKSFTRACEEVENT"]._serialized_start = 61657 + _globals["_EXT4ALLOCDABLOCKSFTRACEEVENT"]._serialized_end = 61755 + _globals["_EXT4ALLOCATEBLOCKSFTRACEEVENT"]._serialized_start = 61758 + _globals["_EXT4ALLOCATEBLOCKSFTRACEEVENT"]._serialized_end = 61951 + _globals["_EXT4ALLOCATEINODEFTRACEEVENT"]._serialized_start = 61953 + _globals["_EXT4ALLOCATEINODEFTRACEEVENT"]._serialized_end = 62036 + _globals["_EXT4BEGINORDEREDTRUNCATEFTRACEEVENT"]._serialized_start = 62038 + _globals["_EXT4BEGINORDEREDTRUNCATEFTRACEEVENT"]._serialized_end = 62119 + _globals["_EXT4COLLAPSERANGEFTRACEEVENT"]._serialized_start = 62121 + _globals["_EXT4COLLAPSERANGEFTRACEEVENT"]._serialized_end = 62206 + _globals["_EXT4DARELEASESPACEFTRACEEVENT"]._serialized_start = 62209 + _globals["_EXT4DARELEASESPACEFTRACEEVENT"]._serialized_end = 62411 + _globals["_EXT4DARESERVESPACEFTRACEEVENT"]._serialized_start = 62414 + _globals["_EXT4DARESERVESPACEFTRACEEVENT"]._serialized_end = 62582 + _globals["_EXT4DAUPDATERESERVESPACEFTRACEEVENT"]._serialized_start = 62585 + _globals["_EXT4DAUPDATERESERVESPACEFTRACEEVENT"]._serialized_end = 62813 + _globals["_EXT4DAWRITEPAGESFTRACEEVENT"]._serialized_start = 62816 + _globals["_EXT4DAWRITEPAGESFTRACEEVENT"]._serialized_end = 63023 + _globals["_EXT4DAWRITEPAGESEXTENTFTRACEEVENT"]._serialized_start = 63025 + _globals["_EXT4DAWRITEPAGESEXTENTFTRACEEVENT"]._serialized_end = 63128 + _globals["_EXT4DIRECTIOENTERFTRACEEVENT"]._serialized_start = 63130 + _globals["_EXT4DIRECTIOENTERFTRACEEVENT"]._serialized_end = 63224 + _globals["_EXT4DIRECTIOEXITFTRACEEVENT"]._serialized_start = 63226 + _globals["_EXT4DIRECTIOEXITFTRACEEVENT"]._serialized_end = 63332 + _globals["_EXT4DISCARDBLOCKSFTRACEEVENT"]._serialized_start = 63334 + _globals["_EXT4DISCARDBLOCKSFTRACEEVENT"]._serialized_end = 63405 + _globals["_EXT4DISCARDPREALLOCATIONSFTRACEEVENT"]._serialized_start = 63407 + _globals["_EXT4DISCARDPREALLOCATIONSFTRACEEVENT"]._serialized_end = 63500 + _globals["_EXT4DROPINODEFTRACEEVENT"]._serialized_start = 63502 + _globals["_EXT4DROPINODEFTRACEEVENT"]._serialized_end = 63568 + _globals["_EXT4ESCACHEEXTENTFTRACEEVENT"]._serialized_start = 63570 + _globals["_EXT4ESCACHEEXTENTFTRACEEVENT"]._serialized_end = 63683 + _globals["_EXT4ESFINDDELAYEDEXTENTRANGEENTERFTRACEEVENT"]._serialized_start = 63685 + _globals["_EXT4ESFINDDELAYEDEXTENTRANGEENTERFTRACEEVENT"]._serialized_end = 63771 + _globals["_EXT4ESFINDDELAYEDEXTENTRANGEEXITFTRACEEVENT"]._serialized_start = 63774 + _globals["_EXT4ESFINDDELAYEDEXTENTRANGEEXITFTRACEEVENT"]._serialized_end = 63902 + _globals["_EXT4ESINSERTEXTENTFTRACEEVENT"]._serialized_start = 63904 + _globals["_EXT4ESINSERTEXTENTFTRACEEVENT"]._serialized_end = 64018 + _globals["_EXT4ESLOOKUPEXTENTENTERFTRACEEVENT"]._serialized_start = 64020 + _globals["_EXT4ESLOOKUPEXTENTENTERFTRACEEVENT"]._serialized_end = 64096 + _globals["_EXT4ESLOOKUPEXTENTEXITFTRACEEVENT"]._serialized_start = 64099 + _globals["_EXT4ESLOOKUPEXTENTEXITFTRACEEVENT"]._serialized_end = 64232 + _globals["_EXT4ESREMOVEEXTENTFTRACEEVENT"]._serialized_start = 64234 + _globals["_EXT4ESREMOVEEXTENTFTRACEEVENT"]._serialized_end = 64318 + _globals["_EXT4ESSHRINKFTRACEEVENT"]._serialized_start = 64320 + _globals["_EXT4ESSHRINKFTRACEEVENT"]._serialized_end = 64433 + _globals["_EXT4ESSHRINKCOUNTFTRACEEVENT"]._serialized_start = 64435 + _globals["_EXT4ESSHRINKCOUNTFTRACEEVENT"]._serialized_end = 64517 + _globals["_EXT4ESSHRINKSCANENTERFTRACEEVENT"]._serialized_start = 64519 + _globals["_EXT4ESSHRINKSCANENTERFTRACEEVENT"]._serialized_end = 64605 + _globals["_EXT4ESSHRINKSCANEXITFTRACEEVENT"]._serialized_start = 64607 + _globals["_EXT4ESSHRINKSCANEXITFTRACEEVENT"]._serialized_end = 64691 + _globals["_EXT4EVICTINODEFTRACEEVENT"]._serialized_start = 64693 + _globals["_EXT4EVICTINODEFTRACEEVENT"]._serialized_end = 64761 + _globals["_EXT4EXTCONVERTTOINITIALIZEDENTERFTRACEEVENT"]._serialized_start = 64764 + _globals["_EXT4EXTCONVERTTOINITIALIZEDENTERFTRACEEVENT"]._serialized_end = 64913 + _globals["_EXT4EXTCONVERTTOINITIALIZEDFASTPATHFTRACEEVENT"]._serialized_start = ( + 64916 + ) + _globals["_EXT4EXTCONVERTTOINITIALIZEDFASTPATHFTRACEEVENT"]._serialized_end = 65115 + _globals["_EXT4EXTHANDLEUNWRITTENEXTENTSFTRACEEVENT"]._serialized_start = 65118 + _globals["_EXT4EXTHANDLEUNWRITTENEXTENTSFTRACEEVENT"]._serialized_end = 65277 + _globals["_EXT4EXTINCACHEFTRACEEVENT"]._serialized_start = 65279 + _globals["_EXT4EXTINCACHEFTRACEEVENT"]._serialized_end = 65359 + _globals["_EXT4EXTLOADEXTENTFTRACEEVENT"]._serialized_start = 65361 + _globals["_EXT4EXTLOADEXTENTFTRACEEVENT"]._serialized_end = 65445 + _globals["_EXT4EXTMAPBLOCKSENTERFTRACEEVENT"]._serialized_start = 65447 + _globals["_EXT4EXTMAPBLOCKSENTERFTRACEEVENT"]._serialized_end = 65549 + _globals["_EXT4EXTMAPBLOCKSEXITFTRACEEVENT"]._serialized_start = 65552 + _globals["_EXT4EXTMAPBLOCKSEXITFTRACEEVENT"]._serialized_end = 65696 + _globals["_EXT4EXTPUTINCACHEFTRACEEVENT"]._serialized_start = 65698 + _globals["_EXT4EXTPUTINCACHEFTRACEEVENT"]._serialized_end = 65796 + _globals["_EXT4EXTREMOVESPACEFTRACEEVENT"]._serialized_start = 65798 + _globals["_EXT4EXTREMOVESPACEFTRACEEVENT"]._serialized_end = 65898 + _globals["_EXT4EXTREMOVESPACEDONEFTRACEEVENT"]._serialized_start = 65901 + _globals["_EXT4EXTREMOVESPACEDONEFTRACEEVENT"]._serialized_end = 66094 + _globals["_EXT4EXTRMIDXFTRACEEVENT"]._serialized_start = 66096 + _globals["_EXT4EXTRMIDXFTRACEEVENT"]._serialized_end = 66161 + _globals["_EXT4EXTRMLEAFFTRACEEVENT"]._serialized_start = 66164 + _globals["_EXT4EXTRMLEAFFTRACEEVENT"]._serialized_end = 66350 + _globals["_EXT4EXTSHOWEXTENTFTRACEEVENT"]._serialized_start = 66352 + _globals["_EXT4EXTSHOWEXTENTFTRACEEVENT"]._serialized_end = 66449 + _globals["_EXT4FALLOCATEENTERFTRACEEVENT"]._serialized_start = 66451 + _globals["_EXT4FALLOCATEENTERFTRACEEVENT"]._serialized_end = 66564 + _globals["_EXT4FALLOCATEEXITFTRACEEVENT"]._serialized_start = 66566 + _globals["_EXT4FALLOCATEEXITFTRACEEVENT"]._serialized_end = 66664 + _globals["_EXT4FINDDELALLOCRANGEFTRACEEVENT"]._serialized_start = 66667 + _globals["_EXT4FINDDELALLOCRANGEFTRACEEVENT"]._serialized_end = 66804 + _globals["_EXT4FORGETFTRACEEVENT"]._serialized_start = 66806 + _globals["_EXT4FORGETFTRACEEVENT"]._serialized_end = 66905 + _globals["_EXT4FREEBLOCKSFTRACEEVENT"]._serialized_start = 66907 + _globals["_EXT4FREEBLOCKSFTRACEEVENT"]._serialized_end = 67019 + _globals["_EXT4FREEINODEFTRACEEVENT"]._serialized_start = 67021 + _globals["_EXT4FREEINODEFTRACEEVENT"]._serialized_end = 67129 + _globals["_EXT4GETIMPLIEDCLUSTERALLOCEXITFTRACEEVENT"]._serialized_start = 67131 + _globals["_EXT4GETIMPLIEDCLUSTERALLOCEXITFTRACEEVENT"]._serialized_end = 67256 + _globals["_EXT4GETRESERVEDCLUSTERALLOCFTRACEEVENT"]._serialized_start = 67258 + _globals["_EXT4GETRESERVEDCLUSTERALLOCFTRACEEVENT"]._serialized_end = 67351 + _globals["_EXT4INDMAPBLOCKSENTERFTRACEEVENT"]._serialized_start = 67353 + _globals["_EXT4INDMAPBLOCKSENTERFTRACEEVENT"]._serialized_end = 67455 + _globals["_EXT4INDMAPBLOCKSEXITFTRACEEVENT"]._serialized_start = 67458 + _globals["_EXT4INDMAPBLOCKSEXITFTRACEEVENT"]._serialized_end = 67602 + _globals["_EXT4INSERTRANGEFTRACEEVENT"]._serialized_start = 67604 + _globals["_EXT4INSERTRANGEFTRACEEVENT"]._serialized_end = 67687 + _globals["_EXT4INVALIDATEPAGEFTRACEEVENT"]._serialized_start = 67689 + _globals["_EXT4INVALIDATEPAGEFTRACEEVENT"]._serialized_end = 67793 + _globals["_EXT4JOURNALSTARTFTRACEEVENT"]._serialized_start = 67796 + _globals["_EXT4JOURNALSTARTFTRACEEVENT"]._serialized_end = 67925 + _globals["_EXT4JOURNALSTARTRESERVEDFTRACEEVENT"]._serialized_start = 67927 + _globals["_EXT4JOURNALSTARTRESERVEDFTRACEEVENT"]._serialized_end = 68005 + _globals["_EXT4JOURNALLEDINVALIDATEPAGEFTRACEEVENT"]._serialized_start = 68007 + _globals["_EXT4JOURNALLEDINVALIDATEPAGEFTRACEEVENT"]._serialized_end = 68121 + _globals["_EXT4JOURNALLEDWRITEENDFTRACEEVENT"]._serialized_start = 68123 + _globals["_EXT4JOURNALLEDWRITEENDFTRACEEVENT"]._serialized_end = 68226 + _globals["_EXT4LOADINODEFTRACEEVENT"]._serialized_start = 68228 + _globals["_EXT4LOADINODEFTRACEEVENT"]._serialized_end = 68280 + _globals["_EXT4LOADINODEBITMAPFTRACEEVENT"]._serialized_start = 68282 + _globals["_EXT4LOADINODEBITMAPFTRACEEVENT"]._serialized_end = 68342 + _globals["_EXT4MARKINODEDIRTYFTRACEEVENT"]._serialized_start = 68344 + _globals["_EXT4MARKINODEDIRTYFTRACEEVENT"]._serialized_end = 68413 + _globals["_EXT4MBBITMAPLOADFTRACEEVENT"]._serialized_start = 68415 + _globals["_EXT4MBBITMAPLOADFTRACEEVENT"]._serialized_end = 68472 + _globals["_EXT4MBBUDDYBITMAPLOADFTRACEEVENT"]._serialized_start = 68474 + _globals["_EXT4MBBUDDYBITMAPLOADFTRACEEVENT"]._serialized_end = 68536 + _globals["_EXT4MBDISCARDPREALLOCATIONSFTRACEEVENT"]._serialized_start = 68538 + _globals["_EXT4MBDISCARDPREALLOCATIONSFTRACEEVENT"]._serialized_end = 68607 + _globals["_EXT4MBNEWGROUPPAFTRACEEVENT"]._serialized_start = 68609 + _globals["_EXT4MBNEWGROUPPAFTRACEEVENT"]._serialized_end = 68718 + _globals["_EXT4MBNEWINODEPAFTRACEEVENT"]._serialized_start = 68720 + _globals["_EXT4MBNEWINODEPAFTRACEEVENT"]._serialized_end = 68829 + _globals["_EXT4MBRELEASEGROUPPAFTRACEEVENT"]._serialized_start = 68831 + _globals["_EXT4MBRELEASEGROUPPAFTRACEEVENT"]._serialized_end = 68912 + _globals["_EXT4MBRELEASEINODEPAFTRACEEVENT"]._serialized_start = 68914 + _globals["_EXT4MBRELEASEINODEPAFTRACEEVENT"]._serialized_end = 69003 + _globals["_EXT4MBALLOCALLOCFTRACEEVENT"]._serialized_start = 69006 + _globals["_EXT4MBALLOCALLOCFTRACEEVENT"]._serialized_end = 69396 + _globals["_EXT4MBALLOCDISCARDFTRACEEVENT"]._serialized_start = 69398 + _globals["_EXT4MBALLOCDISCARDFTRACEEVENT"]._serialized_end = 69519 + _globals["_EXT4MBALLOCFREEFTRACEEVENT"]._serialized_start = 69521 + _globals["_EXT4MBALLOCFREEFTRACEEVENT"]._serialized_end = 69639 + _globals["_EXT4MBALLOCPREALLOCFTRACEEVENT"]._serialized_start = 69642 + _globals["_EXT4MBALLOCPREALLOCFTRACEEVENT"]._serialized_end = 69868 + _globals["_EXT4OTHERINODEUPDATETIMEFTRACEEVENT"]._serialized_start = 69870 + _globals["_EXT4OTHERINODEUPDATETIMEFTRACEEVENT"]._serialized_end = 69991 + _globals["_EXT4PUNCHHOLEFTRACEEVENT"]._serialized_start = 69993 + _globals["_EXT4PUNCHHOLEFTRACEEVENT"]._serialized_end = 70088 + _globals["_EXT4READBLOCKBITMAPLOADFTRACEEVENT"]._serialized_start = 70090 + _globals["_EXT4READBLOCKBITMAPLOADFTRACEEVENT"]._serialized_end = 70172 + _globals["_EXT4READPAGEFTRACEEVENT"]._serialized_start = 70174 + _globals["_EXT4READPAGEFTRACEEVENT"]._serialized_end = 70240 + _globals["_EXT4RELEASEPAGEFTRACEEVENT"]._serialized_start = 70242 + _globals["_EXT4RELEASEPAGEFTRACEEVENT"]._serialized_end = 70311 + _globals["_EXT4REMOVEBLOCKSFTRACEEVENT"]._serialized_start = 70314 + _globals["_EXT4REMOVEBLOCKSFTRACEEVENT"]._serialized_end = 70514 + _globals["_EXT4REQUESTBLOCKSFTRACEEVENT"]._serialized_start = 70517 + _globals["_EXT4REQUESTBLOCKSFTRACEEVENT"]._serialized_end = 70694 + _globals["_EXT4REQUESTINODEFTRACEEVENT"]._serialized_start = 70696 + _globals["_EXT4REQUESTINODEFTRACEEVENT"]._serialized_end = 70765 + _globals["_EXT4SYNCFSFTRACEEVENT"]._serialized_start = 70767 + _globals["_EXT4SYNCFSFTRACEEVENT"]._serialized_end = 70817 + _globals["_EXT4TRIMALLFREEFTRACEEVENT"]._serialized_start = 70819 + _globals["_EXT4TRIMALLFREEFTRACEEVENT"]._serialized_end = 70928 + _globals["_EXT4TRIMEXTENTFTRACEEVENT"]._serialized_start = 70930 + _globals["_EXT4TRIMEXTENTFTRACEEVENT"]._serialized_end = 71038 + _globals["_EXT4TRUNCATEENTERFTRACEEVENT"]._serialized_start = 71040 + _globals["_EXT4TRUNCATEENTERFTRACEEVENT"]._serialized_end = 71112 + _globals["_EXT4TRUNCATEEXITFTRACEEVENT"]._serialized_start = 71114 + _globals["_EXT4TRUNCATEEXITFTRACEEVENT"]._serialized_end = 71185 + _globals["_EXT4UNLINKENTERFTRACEEVENT"]._serialized_start = 71187 + _globals["_EXT4UNLINKENTERFTRACEEVENT"]._serialized_end = 71271 + _globals["_EXT4UNLINKEXITFTRACEEVENT"]._serialized_start = 71273 + _globals["_EXT4UNLINKEXITFTRACEEVENT"]._serialized_end = 71339 + _globals["_EXT4WRITEBEGINFTRACEEVENT"]._serialized_start = 71341 + _globals["_EXT4WRITEBEGINFTRACEEVENT"]._serialized_end = 71435 + _globals["_EXT4WRITEENDFTRACEEVENT"]._serialized_start = 71437 + _globals["_EXT4WRITEENDFTRACEEVENT"]._serialized_end = 71530 + _globals["_EXT4WRITEPAGEFTRACEEVENT"]._serialized_start = 71532 + _globals["_EXT4WRITEPAGEFTRACEEVENT"]._serialized_end = 71599 + _globals["_EXT4WRITEPAGESFTRACEEVENT"]._serialized_start = 71602 + _globals["_EXT4WRITEPAGESFTRACEEVENT"]._serialized_end = 71826 + _globals["_EXT4WRITEPAGESRESULTFTRACEEVENT"]._serialized_start = 71829 + _globals["_EXT4WRITEPAGESRESULTFTRACEEVENT"]._serialized_end = 71991 + _globals["_EXT4ZERORANGEFTRACEEVENT"]._serialized_start = 71993 + _globals["_EXT4ZERORANGEFTRACEEVENT"]._serialized_end = 72088 + _globals["_F2FSDOSUBMITBIOFTRACEEVENT"]._serialized_start = 72090 + _globals["_F2FSDOSUBMITBIOFTRACEEVENT"]._serialized_end = 72190 + _globals["_F2FSEVICTINODEFTRACEEVENT"]._serialized_start = 72193 + _globals["_F2FSEVICTINODEFTRACEEVENT"]._serialized_end = 72335 + _globals["_F2FSFALLOCATEFTRACEEVENT"]._serialized_start = 72338 + _globals["_F2FSFALLOCATEFTRACEEVENT"]._serialized_end = 72476 + _globals["_F2FSGETDATABLOCKFTRACEEVENT"]._serialized_start = 72478 + _globals["_F2FSGETDATABLOCKFTRACEEVENT"]._serialized_end = 72597 + _globals["_F2FSGETVICTIMFTRACEEVENT"]._serialized_start = 72600 + _globals["_F2FSGETVICTIMFTRACEEVENT"]._serialized_end = 72806 + _globals["_F2FSIGETFTRACEEVENT"]._serialized_start = 72809 + _globals["_F2FSIGETFTRACEEVENT"]._serialized_end = 72945 + _globals["_F2FSIGETEXITFTRACEEVENT"]._serialized_start = 72947 + _globals["_F2FSIGETEXITFTRACEEVENT"]._serialized_end = 73011 + _globals["_F2FSNEWINODEFTRACEEVENT"]._serialized_start = 73013 + _globals["_F2FSNEWINODEFTRACEEVENT"]._serialized_end = 73077 + _globals["_F2FSREADPAGEFTRACEEVENT"]._serialized_start = 73080 + _globals["_F2FSREADPAGEFTRACEEVENT"]._serialized_end = 73223 + _globals["_F2FSRESERVENEWBLOCKFTRACEEVENT"]._serialized_start = 73225 + _globals["_F2FSRESERVENEWBLOCKFTRACEEVENT"]._serialized_end = 73304 + _globals["_F2FSSETPAGEDIRTYFTRACEEVENT"]._serialized_start = 73307 + _globals["_F2FSSETPAGEDIRTYFTRACEEVENT"]._serialized_end = 73437 + _globals["_F2FSSUBMITWRITEPAGEFTRACEEVENT"]._serialized_start = 73439 + _globals["_F2FSSUBMITWRITEPAGEFTRACEEVENT"]._serialized_end = 73541 + _globals["_F2FSSYNCFILEENTERFTRACEEVENT"]._serialized_start = 73544 + _globals["_F2FSSYNCFILEENTERFTRACEEVENT"]._serialized_end = 73689 + _globals["_F2FSSYNCFILEEXITFTRACEEVENT"]._serialized_start = 73691 + _globals["_F2FSSYNCFILEEXITFTRACEEVENT"]._serialized_end = 73813 + _globals["_F2FSSYNCFSFTRACEEVENT"]._serialized_start = 73815 + _globals["_F2FSSYNCFSFTRACEEVENT"]._serialized_end = 73880 + _globals["_F2FSTRUNCATEFTRACEEVENT"]._serialized_start = 73883 + _globals["_F2FSTRUNCATEFTRACEEVENT"]._serialized_end = 74023 + _globals["_F2FSTRUNCATEBLOCKSENTERFTRACEEVENT"]._serialized_start = 74025 + _globals["_F2FSTRUNCATEBLOCKSENTERFTRACEEVENT"]._serialized_end = 74131 + _globals["_F2FSTRUNCATEBLOCKSEXITFTRACEEVENT"]._serialized_start = 74133 + _globals["_F2FSTRUNCATEBLOCKSEXITFTRACEEVENT"]._serialized_end = 74207 + _globals["_F2FSTRUNCATEDATABLOCKSRANGEFTRACEEVENT"]._serialized_start = 74209 + _globals["_F2FSTRUNCATEDATABLOCKSRANGEFTRACEEVENT"]._serialized_end = 74315 + _globals["_F2FSTRUNCATEINODEBLOCKSENTERFTRACEEVENT"]._serialized_start = 74317 + _globals["_F2FSTRUNCATEINODEBLOCKSENTERFTRACEEVENT"]._serialized_end = 74428 + _globals["_F2FSTRUNCATEINODEBLOCKSEXITFTRACEEVENT"]._serialized_start = 74430 + _globals["_F2FSTRUNCATEINODEBLOCKSEXITFTRACEEVENT"]._serialized_end = 74509 + _globals["_F2FSTRUNCATENODEFTRACEEVENT"]._serialized_start = 74511 + _globals["_F2FSTRUNCATENODEFTRACEEVENT"]._serialized_end = 74597 + _globals["_F2FSTRUNCATENODESENTERFTRACEEVENT"]._serialized_start = 74599 + _globals["_F2FSTRUNCATENODESENTERFTRACEEVENT"]._serialized_end = 74691 + _globals["_F2FSTRUNCATENODESEXITFTRACEEVENT"]._serialized_start = 74693 + _globals["_F2FSTRUNCATENODESEXITFTRACEEVENT"]._serialized_end = 74766 + _globals["_F2FSTRUNCATEPARTIALNODESFTRACEEVENT"]._serialized_start = 74768 + _globals["_F2FSTRUNCATEPARTIALNODESFTRACEEVENT"]._serialized_end = 74872 + _globals["_F2FSUNLINKENTERFTRACEEVENT"]._serialized_start = 74874 + _globals["_F2FSUNLINKENTERFTRACEEVENT"]._serialized_end = 74972 + _globals["_F2FSUNLINKEXITFTRACEEVENT"]._serialized_start = 74974 + _globals["_F2FSUNLINKEXITFTRACEEVENT"]._serialized_end = 75040 + _globals["_F2FSVMPAGEMKWRITEFTRACEEVENT"]._serialized_start = 75043 + _globals["_F2FSVMPAGEMKWRITEFTRACEEVENT"]._serialized_end = 75174 + _globals["_F2FSWRITEBEGINFTRACEEVENT"]._serialized_start = 75176 + _globals["_F2FSWRITEBEGINFTRACEEVENT"]._serialized_end = 75270 + _globals["_F2FSWRITECHECKPOINTFTRACEEVENT"]._serialized_start = 75272 + _globals["_F2FSWRITECHECKPOINTFTRACEEVENT"]._serialized_end = 75365 + _globals["_F2FSWRITEENDFTRACEEVENT"]._serialized_start = 75367 + _globals["_F2FSWRITEENDFTRACEEVENT"]._serialized_end = 75460 + _globals["_F2FSIOSTATFTRACEEVENT"]._serialized_start = 75463 + _globals["_F2FSIOSTATFTRACEEVENT"]._serialized_end = 75888 + _globals["_F2FSIOSTATLATENCYFTRACEEVENT"]._serialized_start = 75891 + _globals["_F2FSIOSTATLATENCYFTRACEEVENT"]._serialized_end = 76474 + _globals["_F2FSBACKGROUNDGCFTRACEEVENT"]._serialized_start = 76476 + _globals["_F2FSBACKGROUNDGCFTRACEEVENT"]._serialized_end = 76566 + _globals["_F2FSGCBEGINFTRACEEVENT"]._serialized_start = 76569 + _globals["_F2FSGCBEGINFTRACEEVENT"]._serialized_end = 76839 + _globals["_F2FSGCENDFTRACEEVENT"]._serialized_start = 76842 + _globals["_F2FSGCENDFTRACEEVENT"]._serialized_end = 77070 + _globals["_FASTRPCDMASTATFTRACEEVENT"]._serialized_start = 77072 + _globals["_FASTRPCDMASTATFTRACEEVENT"]._serialized_end = 77150 + _globals["_FASTRPCDMAFREEFTRACEEVENT"]._serialized_start = 77152 + _globals["_FASTRPCDMAFREEFTRACEEVENT"]._serialized_end = 77220 + _globals["_FASTRPCDMAALLOCFTRACEEVENT"]._serialized_start = 77222 + _globals["_FASTRPCDMAALLOCFTRACEEVENT"]._serialized_end = 77321 + _globals["_FASTRPCDMAUNMAPFTRACEEVENT"]._serialized_start = 77323 + _globals["_FASTRPCDMAUNMAPFTRACEEVENT"]._serialized_end = 77392 + _globals["_FASTRPCDMAMAPFTRACEEVENT"]._serialized_start = 77394 + _globals["_FASTRPCDMAMAPFTRACEEVENT"]._serialized_end = 77516 + _globals["_FENCEINITFTRACEEVENT"]._serialized_start = 77518 + _globals["_FENCEINITFTRACEEVENT"]._serialized_end = 77606 + _globals["_FENCEDESTROYFTRACEEVENT"]._serialized_start = 77608 + _globals["_FENCEDESTROYFTRACEEVENT"]._serialized_end = 77699 + _globals["_FENCEENABLESIGNALFTRACEEVENT"]._serialized_start = 77701 + _globals["_FENCEENABLESIGNALFTRACEEVENT"]._serialized_end = 77797 + _globals["_FENCESIGNALEDFTRACEEVENT"]._serialized_start = 77799 + _globals["_FENCESIGNALEDFTRACEEVENT"]._serialized_end = 77891 + _globals["_MMFILEMAPADDTOPAGECACHEFTRACEEVENT"]._serialized_start = 77893 + _globals["_MMFILEMAPADDTOPAGECACHEFTRACEEVENT"]._serialized_end = 78001 + _globals["_MMFILEMAPDELETEFROMPAGECACHEFTRACEEVENT"]._serialized_start = 78003 + _globals["_MMFILEMAPDELETEFROMPAGECACHEFTRACEEVENT"]._serialized_end = 78116 + _globals["_PRINTFTRACEEVENT"]._serialized_start = 78118 + _globals["_PRINTFTRACEEVENT"]._serialized_end = 78161 + _globals["_FUNCGRAPHENTRYFTRACEEVENT"]._serialized_start = 78163 + _globals["_FUNCGRAPHENTRYFTRACEEVENT"]._serialized_end = 78219 + _globals["_FUNCGRAPHEXITFTRACEEVENT"]._serialized_start = 78221 + _globals["_FUNCGRAPHEXITFTRACEEVENT"]._serialized_end = 78328 + _globals["_G2DTRACINGMARKWRITEFTRACEEVENT"]._serialized_start = 78330 + _globals["_G2DTRACINGMARKWRITEFTRACEEVENT"]._serialized_end = 78418 + _globals["_GENERICFTRACEEVENT"]._serialized_start = 78421 + _globals["_GENERICFTRACEEVENT"]._serialized_end = 78615 + _globals["_GENERICFTRACEEVENT_FIELD"]._serialized_start = 78521 + _globals["_GENERICFTRACEEVENT_FIELD"]._serialized_end = 78615 + _globals["_GOOGLEICCEVENTFTRACEEVENT"]._serialized_start = 78617 + _globals["_GOOGLEICCEVENTFTRACEEVENT"]._serialized_end = 78678 + _globals["_GOOGLEIRMEVENTFTRACEEVENT"]._serialized_start = 78680 + _globals["_GOOGLEIRMEVENTFTRACEEVENT"]._serialized_end = 78741 + _globals["_GPUMEMTOTALFTRACEEVENT"]._serialized_start = 78743 + _globals["_GPUMEMTOTALFTRACEEVENT"]._serialized_end = 78810 + _globals["_DRMSCHEDJOBFTRACEEVENT"]._serialized_start = 78812 + _globals["_DRMSCHEDJOBFTRACEEVENT"]._serialized_end = 78934 + _globals["_DRMRUNJOBFTRACEEVENT"]._serialized_start = 78936 + _globals["_DRMRUNJOBFTRACEEVENT"]._serialized_end = 79056 + _globals["_DRMSCHEDPROCESSJOBFTRACEEVENT"]._serialized_start = 79058 + _globals["_DRMSCHEDPROCESSJOBFTRACEEVENT"]._serialized_end = 79104 + _globals["_HYPENTERFTRACEEVENT"]._serialized_start = 79106 + _globals["_HYPENTERFTRACEEVENT"]._serialized_end = 79127 + _globals["_HYPEXITFTRACEEVENT"]._serialized_start = 79129 + _globals["_HYPEXITFTRACEEVENT"]._serialized_end = 79149 + _globals["_HOSTHCALLFTRACEEVENT"]._serialized_start = 79151 + _globals["_HOSTHCALLFTRACEEVENT"]._serialized_end = 79202 + _globals["_HOSTSMCFTRACEEVENT"]._serialized_start = 79204 + _globals["_HOSTSMCFTRACEEVENT"]._serialized_end = 79255 + _globals["_HOSTMEMABORTFTRACEEVENT"]._serialized_start = 79257 + _globals["_HOSTMEMABORTFTRACEEVENT"]._serialized_end = 79309 + _globals["_I2CREADFTRACEEVENT"]._serialized_start = 79311 + _globals["_I2CREADFTRACEEVENT"]._serialized_end = 79409 + _globals["_I2CWRITEFTRACEEVENT"]._serialized_start = 79411 + _globals["_I2CWRITEFTRACEEVENT"]._serialized_end = 79523 + _globals["_I2CRESULTFTRACEEVENT"]._serialized_start = 79525 + _globals["_I2CRESULTFTRACEEVENT"]._serialized_end = 79597 + _globals["_I2CREPLYFTRACEEVENT"]._serialized_start = 79599 + _globals["_I2CREPLYFTRACEEVENT"]._serialized_end = 79711 + _globals["_SMBUSREADFTRACEEVENT"]._serialized_start = 79713 + _globals["_SMBUSREADFTRACEEVENT"]._serialized_end = 79819 + _globals["_SMBUSWRITEFTRACEEVENT"]._serialized_start = 79821 + _globals["_SMBUSWRITEFTRACEEVENT"]._serialized_end = 79941 + _globals["_SMBUSRESULTFTRACEEVENT"]._serialized_start = 79944 + _globals["_SMBUSRESULTFTRACEEVENT"]._serialized_end = 80085 + _globals["_SMBUSREPLYFTRACEEVENT"]._serialized_start = 80087 + _globals["_SMBUSREPLYFTRACEEVENT"]._serialized_end = 80207 + _globals["_IONSTATFTRACEEVENT"]._serialized_start = 80209 + _globals["_IONSTATFTRACEEVENT"]._serialized_end = 80286 + _globals["_IPIENTRYFTRACEEVENT"]._serialized_start = 80288 + _globals["_IPIENTRYFTRACEEVENT"]._serialized_end = 80325 + _globals["_IPIEXITFTRACEEVENT"]._serialized_start = 80327 + _globals["_IPIEXITFTRACEEVENT"]._serialized_end = 80363 + _globals["_IPIRAISEFTRACEEVENT"]._serialized_start = 80365 + _globals["_IPIRAISEFTRACEEVENT"]._serialized_end = 80423 + _globals["_SOFTIRQENTRYFTRACEEVENT"]._serialized_start = 80425 + _globals["_SOFTIRQENTRYFTRACEEVENT"]._serialized_end = 80463 + _globals["_SOFTIRQEXITFTRACEEVENT"]._serialized_start = 80465 + _globals["_SOFTIRQEXITFTRACEEVENT"]._serialized_end = 80502 + _globals["_SOFTIRQRAISEFTRACEEVENT"]._serialized_start = 80504 + _globals["_SOFTIRQRAISEFTRACEEVENT"]._serialized_end = 80542 + _globals["_IRQHANDLERENTRYFTRACEEVENT"]._serialized_start = 80544 + _globals["_IRQHANDLERENTRYFTRACEEVENT"]._serialized_end = 80616 + _globals["_IRQHANDLEREXITFTRACEEVENT"]._serialized_start = 80618 + _globals["_IRQHANDLEREXITFTRACEEVENT"]._serialized_end = 80671 + _globals["_KGSLGPUFREQUENCYFTRACEEVENT"]._serialized_start = 80673 + _globals["_KGSLGPUFREQUENCYFTRACEEVENT"]._serialized_end = 80736 + _globals["_KGSLADRENOCMDBATCHQUEUEDFTRACEEVENT"]._serialized_start = 80738 + _globals["_KGSLADRENOCMDBATCHQUEUEDFTRACEEVENT"]._serialized_end = 80851 + _globals["_KGSLADRENOCMDBATCHSUBMITTEDFTRACEEVENT"]._serialized_start = 80854 + _globals["_KGSLADRENOCMDBATCHSUBMITTEDFTRACEEVENT"]._serialized_end = 81103 + _globals["_KGSLADRENOCMDBATCHSYNCFTRACEEVENT"]._serialized_start = 81105 + _globals["_KGSLADRENOCMDBATCHSYNCFTRACEEVENT"]._serialized_end = 81200 + _globals["_KGSLADRENOCMDBATCHRETIREDFTRACEEVENT"]._serialized_start = 81203 + _globals["_KGSLADRENOCMDBATCHRETIREDFTRACEEVENT"]._serialized_end = 81544 + _globals["_ALLOCPAGESIOMMUENDFTRACEEVENT"]._serialized_start = 81546 + _globals["_ALLOCPAGESIOMMUENDFTRACEEVENT"]._serialized_end = 81611 + _globals["_ALLOCPAGESIOMMUFAILFTRACEEVENT"]._serialized_start = 81613 + _globals["_ALLOCPAGESIOMMUFAILFTRACEEVENT"]._serialized_end = 81679 + _globals["_ALLOCPAGESIOMMUSTARTFTRACEEVENT"]._serialized_start = 81681 + _globals["_ALLOCPAGESIOMMUSTARTFTRACEEVENT"]._serialized_end = 81748 + _globals["_ALLOCPAGESSYSENDFTRACEEVENT"]._serialized_start = 81750 + _globals["_ALLOCPAGESSYSENDFTRACEEVENT"]._serialized_end = 81813 + _globals["_ALLOCPAGESSYSFAILFTRACEEVENT"]._serialized_start = 81815 + _globals["_ALLOCPAGESSYSFAILFTRACEEVENT"]._serialized_end = 81879 + _globals["_ALLOCPAGESSYSSTARTFTRACEEVENT"]._serialized_start = 81881 + _globals["_ALLOCPAGESSYSSTARTFTRACEEVENT"]._serialized_end = 81946 + _globals["_DMAALLOCCONTIGUOUSRETRYFTRACEEVENT"]._serialized_start = 81948 + _globals["_DMAALLOCCONTIGUOUSRETRYFTRACEEVENT"]._serialized_end = 81999 + _globals["_IOMMUMAPRANGEFTRACEEVENT"]._serialized_start = 82001 + _globals["_IOMMUMAPRANGEFTRACEEVENT"]._serialized_end = 82084 + _globals["_IOMMUSECPTBLMAPRANGEENDFTRACEEVENT"]._serialized_start = 82086 + _globals["_IOMMUSECPTBLMAPRANGEENDFTRACEEVENT"]._serialized_end = 82188 + _globals["_IOMMUSECPTBLMAPRANGESTARTFTRACEEVENT"]._serialized_start = 82190 + _globals["_IOMMUSECPTBLMAPRANGESTARTFTRACEEVENT"]._serialized_end = 82294 + _globals["_IONALLOCBUFFERENDFTRACEEVENT"]._serialized_start = 82296 + _globals["_IONALLOCBUFFERENDFTRACEEVENT"]._serialized_end = 82408 + _globals["_IONALLOCBUFFERFAILFTRACEEVENT"]._serialized_start = 82411 + _globals["_IONALLOCBUFFERFAILFTRACEEVENT"]._serialized_end = 82539 + _globals["_IONALLOCBUFFERFALLBACKFTRACEEVENT"]._serialized_start = 82542 + _globals["_IONALLOCBUFFERFALLBACKFTRACEEVENT"]._serialized_end = 82674 + _globals["_IONALLOCBUFFERSTARTFTRACEEVENT"]._serialized_start = 82676 + _globals["_IONALLOCBUFFERSTARTFTRACEEVENT"]._serialized_end = 82790 + _globals["_IONCPALLOCRETRYFTRACEEVENT"]._serialized_start = 82792 + _globals["_IONCPALLOCRETRYFTRACEEVENT"]._serialized_end = 82835 + _globals["_IONCPSECUREBUFFERENDFTRACEEVENT"]._serialized_start = 82837 + _globals["_IONCPSECUREBUFFERENDFTRACEEVENT"]._serialized_end = 82932 + _globals["_IONCPSECUREBUFFERSTARTFTRACEEVENT"]._serialized_start = 82934 + _globals["_IONCPSECUREBUFFERSTARTFTRACEEVENT"]._serialized_end = 83031 + _globals["_IONPREFETCHINGFTRACEEVENT"]._serialized_start = 83033 + _globals["_IONPREFETCHINGFTRACEEVENT"]._serialized_end = 83073 + _globals["_IONSECURECMAADDTOPOOLENDFTRACEEVENT"]._serialized_start = 83075 + _globals["_IONSECURECMAADDTOPOOLENDFTRACEEVENT"]._serialized_end = 83166 + _globals["_IONSECURECMAADDTOPOOLSTARTFTRACEEVENT"]._serialized_start = 83168 + _globals["_IONSECURECMAADDTOPOOLSTARTFTRACEEVENT"]._serialized_end = 83261 + _globals["_IONSECURECMAALLOCATEENDFTRACEEVENT"]._serialized_start = 83263 + _globals["_IONSECURECMAALLOCATEENDFTRACEEVENT"]._serialized_end = 83361 + _globals["_IONSECURECMAALLOCATESTARTFTRACEEVENT"]._serialized_start = 83363 + _globals["_IONSECURECMAALLOCATESTARTFTRACEEVENT"]._serialized_end = 83463 + _globals["_IONSECURECMASHRINKPOOLENDFTRACEEVENT"]._serialized_start = 83465 + _globals["_IONSECURECMASHRINKPOOLENDFTRACEEVENT"]._serialized_end = 83547 + _globals["_IONSECURECMASHRINKPOOLSTARTFTRACEEVENT"]._serialized_start = 83549 + _globals["_IONSECURECMASHRINKPOOLSTARTFTRACEEVENT"]._serialized_end = 83633 + _globals["_KFREEFTRACEEVENT"]._serialized_start = 83635 + _globals["_KFREEFTRACEEVENT"]._serialized_end = 83685 + _globals["_KMALLOCFTRACEEVENT"]._serialized_start = 83687 + _globals["_KMALLOCFTRACEEVENT"]._serialized_end = 83798 + _globals["_KMALLOCNODEFTRACEEVENT"]._serialized_start = 83801 + _globals["_KMALLOCNODEFTRACEEVENT"]._serialized_end = 83930 + _globals["_KMEMCACHEALLOCFTRACEEVENT"]._serialized_start = 83932 + _globals["_KMEMCACHEALLOCFTRACEEVENT"]._serialized_end = 84050 + _globals["_KMEMCACHEALLOCNODEFTRACEEVENT"]._serialized_start = 84053 + _globals["_KMEMCACHEALLOCNODEFTRACEEVENT"]._serialized_end = 84189 + _globals["_KMEMCACHEFREEFTRACEEVENT"]._serialized_start = 84191 + _globals["_KMEMCACHEFREEFTRACEEVENT"]._serialized_end = 84249 + _globals["_MIGRATEPAGESENDFTRACEEVENT"]._serialized_start = 84251 + _globals["_MIGRATEPAGESENDFTRACEEVENT"]._serialized_end = 84293 + _globals["_MIGRATEPAGESSTARTFTRACEEVENT"]._serialized_start = 84295 + _globals["_MIGRATEPAGESSTARTFTRACEEVENT"]._serialized_end = 84339 + _globals["_MIGRATERETRYFTRACEEVENT"]._serialized_start = 84341 + _globals["_MIGRATERETRYFTRACEEVENT"]._serialized_end = 84381 + _globals["_MMPAGEALLOCFTRACEEVENT"]._serialized_start = 84383 + _globals["_MMPAGEALLOCFTRACEEVENT"]._serialized_end = 84489 + _globals["_MMPAGEALLOCEXTFRAGFTRACEEVENT"]._serialized_start = 84492 + _globals["_MMPAGEALLOCEXTFRAGFTRACEEVENT"]._serialized_end = 84678 + _globals["_MMPAGEALLOCZONELOCKEDFTRACEEVENT"]._serialized_start = 84680 + _globals["_MMPAGEALLOCZONELOCKEDFTRACEEVENT"]._serialized_end = 84777 + _globals["_MMPAGEFREEFTRACEEVENT"]._serialized_start = 84779 + _globals["_MMPAGEFREEFTRACEEVENT"]._serialized_end = 84844 + _globals["_MMPAGEFREEBATCHEDFTRACEEVENT"]._serialized_start = 84846 + _globals["_MMPAGEFREEBATCHEDFTRACEEVENT"]._serialized_end = 84917 + _globals["_MMPAGEPCPUDRAINFTRACEEVENT"]._serialized_start = 84919 + _globals["_MMPAGEPCPUDRAINFTRACEEVENT"]._serialized_end = 85010 + _globals["_RSSSTATFTRACEEVENT"]._serialized_start = 85012 + _globals["_RSSSTATFTRACEEVENT"]._serialized_end = 85091 + _globals["_IONHEAPSHRINKFTRACEEVENT"]._serialized_start = 85093 + _globals["_IONHEAPSHRINKFTRACEEVENT"]._serialized_end = 85176 + _globals["_IONHEAPGROWFTRACEEVENT"]._serialized_start = 85178 + _globals["_IONHEAPGROWFTRACEEVENT"]._serialized_end = 85259 + _globals["_IONBUFFERCREATEFTRACEEVENT"]._serialized_start = 85261 + _globals["_IONBUFFERCREATEFTRACEEVENT"]._serialized_end = 85316 + _globals["_IONBUFFERDESTROYFTRACEEVENT"]._serialized_start = 85318 + _globals["_IONBUFFERDESTROYFTRACEEVENT"]._serialized_end = 85374 + _globals["_KVMACCESSFAULTFTRACEEVENT"]._serialized_start = 85376 + _globals["_KVMACCESSFAULTFTRACEEVENT"]._serialized_end = 85416 + _globals["_KVMACKIRQFTRACEEVENT"]._serialized_start = 85418 + _globals["_KVMACKIRQFTRACEEVENT"]._serialized_end = 85470 + _globals["_KVMAGEHVAFTRACEEVENT"]._serialized_start = 85472 + _globals["_KVMAGEHVAFTRACEEVENT"]._serialized_end = 85522 + _globals["_KVMAGEPAGEFTRACEEVENT"]._serialized_start = 85524 + _globals["_KVMAGEPAGEFTRACEEVENT"]._serialized_end = 85608 + _globals["_KVMARMCLEARDEBUGFTRACEEVENT"]._serialized_start = 85610 + _globals["_KVMARMCLEARDEBUGFTRACEEVENT"]._serialized_end = 85660 + _globals["_KVMARMSETDREG32FTRACEEVENT"]._serialized_start = 85662 + _globals["_KVMARMSETDREG32FTRACEEVENT"]._serialized_end = 85719 + _globals["_KVMARMSETREGSETFTRACEEVENT"]._serialized_start = 85721 + _globals["_KVMARMSETREGSETFTRACEEVENT"]._serialized_end = 85776 + _globals["_KVMARMSETUPDEBUGFTRACEEVENT"]._serialized_start = 85778 + _globals["_KVMARMSETUPDEBUGFTRACEEVENT"]._serialized_end = 85842 + _globals["_KVMENTRYFTRACEEVENT"]._serialized_start = 85844 + _globals["_KVMENTRYFTRACEEVENT"]._serialized_end = 85882 + _globals["_KVMEXITFTRACEEVENT"]._serialized_start = 85884 + _globals["_KVMEXITFTRACEEVENT"]._serialized_end = 85950 + _globals["_KVMFPUFTRACEEVENT"]._serialized_start = 85952 + _globals["_KVMFPUFTRACEEVENT"]._serialized_end = 85985 + _globals["_KVMGETTIMERMAPFTRACEEVENT"]._serialized_start = 85987 + _globals["_KVMGETTIMERMAPFTRACEEVENT"]._serialized_end = 86098 + _globals["_KVMGUESTFAULTFTRACEEVENT"]._serialized_start = 86100 + _globals["_KVMGUESTFAULTFTRACEEVENT"]._serialized_end = 86184 + _globals["_KVMHANDLESYSREGFTRACEEVENT"]._serialized_start = 86186 + _globals["_KVMHANDLESYSREGFTRACEEVENT"]._serialized_end = 86227 + _globals["_KVMHVCARM64FTRACEEVENT"]._serialized_start = 86229 + _globals["_KVMHVCARM64FTRACEEVENT"]._serialized_end = 86295 + _globals["_KVMIRQLINEFTRACEEVENT"]._serialized_start = 86297 + _globals["_KVMIRQLINEFTRACEEVENT"]._serialized_end = 86384 + _globals["_KVMMMIOFTRACEEVENT"]._serialized_start = 86386 + _globals["_KVMMMIOFTRACEEVENT"]._serialized_end = 86459 + _globals["_KVMMMIOEMULATEFTRACEEVENT"]._serialized_start = 86461 + _globals["_KVMMMIOEMULATEFTRACEEVENT"]._serialized_end = 86534 + _globals["_KVMSETGUESTDEBUGFTRACEEVENT"]._serialized_start = 86536 + _globals["_KVMSETGUESTDEBUGFTRACEEVENT"]._serialized_end = 86600 + _globals["_KVMSETIRQFTRACEEVENT"]._serialized_start = 86602 + _globals["_KVMSETIRQFTRACEEVENT"]._serialized_end = 86675 + _globals["_KVMSETSPTEHVAFTRACEEVENT"]._serialized_start = 86677 + _globals["_KVMSETSPTEHVAFTRACEEVENT"]._serialized_end = 86716 + _globals["_KVMSETWAYFLUSHFTRACEEVENT"]._serialized_start = 86718 + _globals["_KVMSETWAYFLUSHFTRACEEVENT"]._serialized_end = 86777 + _globals["_KVMSYSACCESSFTRACEEVENT"]._serialized_start = 86780 + _globals["_KVMSYSACCESSFTRACEEVENT"]._serialized_end = 86919 + _globals["_KVMTESTAGEHVAFTRACEEVENT"]._serialized_start = 86921 + _globals["_KVMTESTAGEHVAFTRACEEVENT"]._serialized_end = 86960 + _globals["_KVMTIMEREMULATEFTRACEEVENT"]._serialized_start = 86962 + _globals["_KVMTIMEREMULATEFTRACEEVENT"]._serialized_end = 87030 + _globals["_KVMTIMERHRTIMEREXPIREFTRACEEVENT"]._serialized_start = 87032 + _globals["_KVMTIMERHRTIMEREXPIREFTRACEEVENT"]._serialized_end = 87085 + _globals["_KVMTIMERRESTORESTATEFTRACEEVENT"]._serialized_start = 87087 + _globals["_KVMTIMERRESTORESTATEFTRACEEVENT"]._serialized_end = 87166 + _globals["_KVMTIMERSAVESTATEFTRACEEVENT"]._serialized_start = 87168 + _globals["_KVMTIMERSAVESTATEFTRACEEVENT"]._serialized_end = 87244 + _globals["_KVMTIMERUPDATEIRQFTRACEEVENT"]._serialized_start = 87246 + _globals["_KVMTIMERUPDATEIRQFTRACEEVENT"]._serialized_end = 87321 + _globals["_KVMTOGGLECACHEFTRACEEVENT"]._serialized_start = 87323 + _globals["_KVMTOGGLECACHEFTRACEEVENT"]._serialized_end = 87393 + _globals["_KVMUNMAPHVARANGEFTRACEEVENT"]._serialized_start = 87395 + _globals["_KVMUNMAPHVARANGEFTRACEEVENT"]._serialized_end = 87452 + _globals["_KVMUSERSPACEEXITFTRACEEVENT"]._serialized_start = 87454 + _globals["_KVMUSERSPACEEXITFTRACEEVENT"]._serialized_end = 87499 + _globals["_KVMVCPUWAKEUPFTRACEEVENT"]._serialized_start = 87501 + _globals["_KVMVCPUWAKEUPFTRACEEVENT"]._serialized_end = 87570 + _globals["_KVMWFXARM64FTRACEEVENT"]._serialized_start = 87572 + _globals["_KVMWFXARM64FTRACEEVENT"]._serialized_end = 87629 + _globals["_TRAPREGFTRACEEVENT"]._serialized_start = 87631 + _globals["_TRAPREGFTRACEEVENT"]._serialized_end = 87715 + _globals["_VGICUPDATEIRQPENDINGFTRACEEVENT"]._serialized_start = 87717 + _globals["_VGICUPDATEIRQPENDINGFTRACEEVENT"]._serialized_end = 87795 + _globals["_LOWMEMORYKILLFTRACEEVENT"]._serialized_start = 87797 + _globals["_LOWMEMORYKILLFTRACEEVENT"]._serialized_end = 87913 + _globals["_LWISTRACINGMARKWRITEFTRACEEVENT"]._serialized_start = 87915 + _globals["_LWISTRACINGMARKWRITEFTRACEEVENT"]._serialized_end = 88028 + _globals["_MALITRACINGMARKWRITEFTRACEEVENT"]._serialized_start = 88030 + _globals["_MALITRACINGMARKWRITEFTRACEEVENT"]._serialized_end = 88119 + _globals["_MALIMALIKCPUCQSSETFTRACEEVENT"]._serialized_start = 88121 + _globals["_MALIMALIKCPUCQSSETFTRACEEVENT"]._serialized_end = 88238 + _globals["_MALIMALIKCPUCQSWAITSTARTFTRACEEVENT"]._serialized_start = 88240 + _globals["_MALIMALIKCPUCQSWAITSTARTFTRACEEVENT"]._serialized_end = 88363 + _globals["_MALIMALIKCPUCQSWAITENDFTRACEEVENT"]._serialized_start = 88365 + _globals["_MALIMALIKCPUCQSWAITENDFTRACEEVENT"]._serialized_end = 88486 + _globals["_MALIMALIKCPUFENCESIGNALFTRACEEVENT"]._serialized_start = 88488 + _globals["_MALIMALIKCPUFENCESIGNALFTRACEEVENT"]._serialized_end = 88610 + _globals["_MALIMALIKCPUFENCEWAITSTARTFTRACEEVENT"]._serialized_start = 88612 + _globals["_MALIMALIKCPUFENCEWAITSTARTFTRACEEVENT"]._serialized_end = 88737 + _globals["_MALIMALIKCPUFENCEWAITENDFTRACEEVENT"]._serialized_start = 88739 + _globals["_MALIMALIKCPUFENCEWAITENDFTRACEEVENT"]._serialized_end = 88862 + _globals["_MALIMALICSFINTERRUPTSTARTFTRACEEVENT"]._serialized_start = 88864 + _globals["_MALIMALICSFINTERRUPTSTARTFTRACEEVENT"]._serialized_end = 88956 + _globals["_MALIMALICSFINTERRUPTENDFTRACEEVENT"]._serialized_start = 88958 + _globals["_MALIMALICSFINTERRUPTENDFTRACEEVENT"]._serialized_end = 89048 + _globals[ + "_MALIMALIPMMCUHCTLCORESDOWNSCALENOTIFYPENDFTRACEEVENT" + ]._serialized_start = 89050 + _globals[ + "_MALIMALIPMMCUHCTLCORESDOWNSCALENOTIFYPENDFTRACEEVENT" + ]._serialized_end = 89158 + _globals["_MALIMALIPMMCUHCTLCORESNOTIFYPENDFTRACEEVENT"]._serialized_start = 89160 + _globals["_MALIMALIPMMCUHCTLCORESNOTIFYPENDFTRACEEVENT"]._serialized_end = 89259 + _globals["_MALIMALIPMMCUHCTLCOREINACTIVEPENDFTRACEEVENT"]._serialized_start = 89261 + _globals["_MALIMALIPMMCUHCTLCOREINACTIVEPENDFTRACEEVENT"]._serialized_end = 89361 + _globals["_MALIMALIPMMCUHCTLMCUONRECHECKFTRACEEVENT"]._serialized_start = 89363 + _globals["_MALIMALIPMMCUHCTLMCUONRECHECKFTRACEEVENT"]._serialized_end = 89459 + _globals["_MALIMALIPMMCUHCTLSHADERSCOREOFFPENDFTRACEEVENT"]._serialized_start = ( + 89461 + ) + _globals["_MALIMALIPMMCUHCTLSHADERSCOREOFFPENDFTRACEEVENT"]._serialized_end = 89563 + _globals["_MALIMALIPMMCUHCTLSHADERSPENDOFFFTRACEEVENT"]._serialized_start = 89565 + _globals["_MALIMALIPMMCUHCTLSHADERSPENDOFFFTRACEEVENT"]._serialized_end = 89663 + _globals["_MALIMALIPMMCUHCTLSHADERSPENDONFTRACEEVENT"]._serialized_start = 89665 + _globals["_MALIMALIPMMCUHCTLSHADERSPENDONFTRACEEVENT"]._serialized_end = 89762 + _globals["_MALIMALIPMMCUHCTLSHADERSREADYOFFFTRACEEVENT"]._serialized_start = 89764 + _globals["_MALIMALIPMMCUHCTLSHADERSREADYOFFFTRACEEVENT"]._serialized_end = 89863 + _globals["_MALIMALIPMMCUINSLEEPFTRACEEVENT"]._serialized_start = 89865 + _globals["_MALIMALIPMMCUINSLEEPFTRACEEVENT"]._serialized_end = 89952 + _globals["_MALIMALIPMMCUOFFFTRACEEVENT"]._serialized_start = 89954 + _globals["_MALIMALIPMMCUOFFFTRACEEVENT"]._serialized_end = 90037 + _globals["_MALIMALIPMMCUONFTRACEEVENT"]._serialized_start = 90039 + _globals["_MALIMALIPMMCUONFTRACEEVENT"]._serialized_end = 90121 + _globals["_MALIMALIPMMCUONCOREATTRUPDATEPENDFTRACEEVENT"]._serialized_start = 90123 + _globals["_MALIMALIPMMCUONCOREATTRUPDATEPENDFTRACEEVENT"]._serialized_end = 90223 + _globals["_MALIMALIPMMCUONGLBREINITPENDFTRACEEVENT"]._serialized_start = 90225 + _globals["_MALIMALIPMMCUONGLBREINITPENDFTRACEEVENT"]._serialized_end = 90320 + _globals["_MALIMALIPMMCUONHALTFTRACEEVENT"]._serialized_start = 90322 + _globals["_MALIMALIPMMCUONHALTFTRACEEVENT"]._serialized_end = 90408 + _globals["_MALIMALIPMMCUONHWCNTDISABLEFTRACEEVENT"]._serialized_start = 90410 + _globals["_MALIMALIPMMCUONHWCNTDISABLEFTRACEEVENT"]._serialized_end = 90504 + _globals["_MALIMALIPMMCUONHWCNTENABLEFTRACEEVENT"]._serialized_start = 90506 + _globals["_MALIMALIPMMCUONHWCNTENABLEFTRACEEVENT"]._serialized_end = 90599 + _globals["_MALIMALIPMMCUONPENDHALTFTRACEEVENT"]._serialized_start = 90601 + _globals["_MALIMALIPMMCUONPENDHALTFTRACEEVENT"]._serialized_end = 90691 + _globals["_MALIMALIPMMCUONPENDSLEEPFTRACEEVENT"]._serialized_start = 90693 + _globals["_MALIMALIPMMCUONPENDSLEEPFTRACEEVENT"]._serialized_end = 90784 + _globals["_MALIMALIPMMCUONSLEEPINITIATEFTRACEEVENT"]._serialized_start = 90786 + _globals["_MALIMALIPMMCUONSLEEPINITIATEFTRACEEVENT"]._serialized_end = 90881 + _globals["_MALIMALIPMMCUPENDOFFFTRACEEVENT"]._serialized_start = 90883 + _globals["_MALIMALIPMMCUPENDOFFFTRACEEVENT"]._serialized_end = 90970 + _globals["_MALIMALIPMMCUPENDONRELOADFTRACEEVENT"]._serialized_start = 90972 + _globals["_MALIMALIPMMCUPENDONRELOADFTRACEEVENT"]._serialized_end = 91064 + _globals["_MALIMALIPMMCUPOWERDOWNFTRACEEVENT"]._serialized_start = 91066 + _globals["_MALIMALIPMMCUPOWERDOWNFTRACEEVENT"]._serialized_end = 91155 + _globals["_MALIMALIPMMCURESETWAITFTRACEEVENT"]._serialized_start = 91157 + _globals["_MALIMALIPMMCURESETWAITFTRACEEVENT"]._serialized_end = 91246 + _globals["_MDPCMDKICKOFFFTRACEEVENT"]._serialized_start = 91248 + _globals["_MDPCMDKICKOFFFTRACEEVENT"]._serialized_end = 91312 + _globals["_MDPCOMMITFTRACEEVENT"]._serialized_start = 91314 + _globals["_MDPCOMMITFTRACEEVENT"]._serialized_end = 91404 + _globals["_MDPPERFSETOTFTRACEEVENT"]._serialized_start = 91406 + _globals["_MDPPERFSETOTFTRACEEVENT"]._serialized_end = 91497 + _globals["_MDPSSPPCHANGEFTRACEEVENT"]._serialized_start = 91500 + _globals["_MDPSSPPCHANGEFTRACEEVENT"]._serialized_end = 91768 + _globals["_TRACINGMARKWRITEFTRACEEVENT"]._serialized_start = 91770 + _globals["_TRACINGMARKWRITEFTRACEEVENT"]._serialized_end = 91853 + _globals["_MDPCMDPINGPONGDONEFTRACEEVENT"]._serialized_start = 91855 + _globals["_MDPCMDPINGPONGDONEFTRACEEVENT"]._serialized_end = 91955 + _globals["_MDPCOMPAREBWFTRACEEVENT"]._serialized_start = 91958 + _globals["_MDPCOMPAREBWFTRACEEVENT"]._serialized_end = 92122 + _globals["_MDPPERFSETPANICLUTSFTRACEEVENT"]._serialized_start = 92124 + _globals["_MDPPERFSETPANICLUTSFTRACEEVENT"]._serialized_end = 92236 + _globals["_MDPSSPPSETFTRACEEVENT"]._serialized_start = 92239 + _globals["_MDPSSPPSETFTRACEEVENT"]._serialized_end = 92504 + _globals["_MDPCMDREADPTRDONEFTRACEEVENT"]._serialized_start = 92506 + _globals["_MDPCMDREADPTRDONEFTRACEEVENT"]._serialized_end = 92571 + _globals["_MDPMISRCRCFTRACEEVENT"]._serialized_start = 92573 + _globals["_MDPMISRCRCFTRACEEVENT"]._serialized_end = 92646 + _globals["_MDPPERFSETQOSLUTSFTRACEEVENT"]._serialized_start = 92648 + _globals["_MDPPERFSETQOSLUTSFTRACEEVENT"]._serialized_end = 92773 + _globals["_MDPTRACECOUNTERFTRACEEVENT"]._serialized_start = 92775 + _globals["_MDPTRACECOUNTERFTRACEEVENT"]._serialized_end = 92853 + _globals["_MDPCMDRELEASEBWFTRACEEVENT"]._serialized_start = 92855 + _globals["_MDPCMDRELEASEBWFTRACEEVENT"]._serialized_end = 92900 + _globals["_MDPMIXERUPDATEFTRACEEVENT"]._serialized_start = 92902 + _globals["_MDPMIXERUPDATEFTRACEEVENT"]._serialized_end = 92948 + _globals["_MDPPERFSETWMLEVELSFTRACEEVENT"]._serialized_start = 92951 + _globals["_MDPPERFSETWMLEVELSFTRACEEVENT"]._serialized_end = 93111 + _globals["_MDPVIDEOUNDERRUNDONEFTRACEEVENT"]._serialized_start = 93113 + _globals["_MDPVIDEOUNDERRUNDONEFTRACEEVENT"]._serialized_end = 93185 + _globals["_MDPCMDWAITPINGPONGFTRACEEVENT"]._serialized_start = 93187 + _globals["_MDPCMDWAITPINGPONGFTRACEEVENT"]._serialized_end = 93256 + _globals["_MDPPERFPREFILLCALCFTRACEEVENT"]._serialized_start = 93259 + _globals["_MDPPERFPREFILLCALCFTRACEEVENT"]._serialized_end = 93465 + _globals["_MDPPERFUPDATEBUSFTRACEEVENT"]._serialized_start = 93467 + _globals["_MDPPERFUPDATEBUSFTRACEEVENT"]._serialized_end = 93548 + _globals["_ROTATORBWAOASCONTEXTFTRACEEVENT"]._serialized_start = 93550 + _globals["_ROTATORBWAOASCONTEXTFTRACEEVENT"]._serialized_end = 93598 + _globals["_MMEVENTRECORDFTRACEEVENT"]._serialized_start = 93600 + _globals["_MMEVENTRECORDFTRACEEVENT"]._serialized_end = 93689 + _globals["_NETIFRECEIVESKBFTRACEEVENT"]._serialized_start = 93691 + _globals["_NETIFRECEIVESKBFTRACEEVENT"]._serialized_end = 93763 + _globals["_NETDEVXMITFTRACEEVENT"]._serialized_start = 93765 + _globals["_NETDEVXMITFTRACEEVENT"]._serialized_end = 93844 + _globals["_NAPIGRORECEIVEENTRYFTRACEEVENT"]._serialized_start = 93847 + _globals["_NAPIGRORECEIVEENTRYFTRACEEVENT"]._serialized_end = 94226 + _globals["_NAPIGRORECEIVEEXITFTRACEEVENT"]._serialized_start = 94228 + _globals["_NAPIGRORECEIVEEXITFTRACEEVENT"]._serialized_end = 94272 + _globals["_OOMSCOREADJUPDATEFTRACEEVENT"]._serialized_start = 94274 + _globals["_OOMSCOREADJUPDATEFTRACEEVENT"]._serialized_end = 94354 + _globals["_MARKVICTIMFTRACEEVENT"]._serialized_start = 94356 + _globals["_MARKVICTIMFTRACEEVENT"]._serialized_end = 94392 + _globals["_DSICMDFIFOSTATUSFTRACEEVENT"]._serialized_start = 94394 + _globals["_DSICMDFIFOSTATUSFTRACEEVENT"]._serialized_end = 94456 + _globals["_DSIRXFTRACEEVENT"]._serialized_start = 94458 + _globals["_DSIRXFTRACEEVENT"]._serialized_end = 94505 + _globals["_DSITXFTRACEEVENT"]._serialized_start = 94507 + _globals["_DSITXFTRACEEVENT"]._serialized_end = 94569 + _globals["_PANELWRITEGENERICFTRACEEVENT"]._serialized_start = 94571 + _globals["_PANELWRITEGENERICFTRACEEVENT"]._serialized_end = 94698 + _globals["_SCHEDSWITCHWITHCTRSFTRACEEVENT"]._serialized_start = 94701 + _globals["_SCHEDSWITCHWITHCTRSFTRACEEVENT"]._serialized_end = 95089 + _globals["_PIXELMMKSWAPDWAKEFTRACEEVENT"]._serialized_start = 95091 + _globals["_PIXELMMKSWAPDWAKEFTRACEEVENT"]._serialized_end = 95139 + _globals["_PIXELMMKSWAPDDONEFTRACEEVENT"]._serialized_start = 95141 + _globals["_PIXELMMKSWAPDDONEFTRACEEVENT"]._serialized_end = 95225 + _globals["_CPUFREQUENCYFTRACEEVENT"]._serialized_start = 95227 + _globals["_CPUFREQUENCYFTRACEEVENT"]._serialized_end = 95283 + _globals["_CPUFREQUENCYLIMITSFTRACEEVENT"]._serialized_start = 95285 + _globals["_CPUFREQUENCYLIMITSFTRACEEVENT"]._serialized_end = 95368 + _globals["_CPUIDLEFTRACEEVENT"]._serialized_start = 95370 + _globals["_CPUIDLEFTRACEEVENT"]._serialized_end = 95421 + _globals["_CLOCKENABLEFTRACEEVENT"]._serialized_start = 95423 + _globals["_CLOCKENABLEFTRACEEVENT"]._serialized_end = 95492 + _globals["_CLOCKDISABLEFTRACEEVENT"]._serialized_start = 95494 + _globals["_CLOCKDISABLEFTRACEEVENT"]._serialized_end = 95564 + _globals["_CLOCKSETRATEFTRACEEVENT"]._serialized_start = 95566 + _globals["_CLOCKSETRATEFTRACEEVENT"]._serialized_end = 95636 + _globals["_SUSPENDRESUMEFTRACEEVENT"]._serialized_start = 95638 + _globals["_SUSPENDRESUMEFTRACEEVENT"]._serialized_end = 95708 + _globals["_GPUFREQUENCYFTRACEEVENT"]._serialized_start = 95710 + _globals["_GPUFREQUENCYFTRACEEVENT"]._serialized_end = 95766 + _globals["_WAKEUPSOURCEACTIVATEFTRACEEVENT"]._serialized_start = 95768 + _globals["_WAKEUPSOURCEACTIVATEFTRACEEVENT"]._serialized_end = 95830 + _globals["_WAKEUPSOURCEDEACTIVATEFTRACEEVENT"]._serialized_start = 95832 + _globals["_WAKEUPSOURCEDEACTIVATEFTRACEEVENT"]._serialized_end = 95896 + _globals["_GPUWORKPERIODFTRACEEVENT"]._serialized_start = 95899 + _globals["_GPUWORKPERIODFTRACEEVENT"]._serialized_end = 96032 + _globals["_DEVICEPMCALLBACKSTARTFTRACEEVENT"]._serialized_start = 96034 + _globals["_DEVICEPMCALLBACKSTARTFTRACEEVENT"]._serialized_end = 96147 + _globals["_DEVICEPMCALLBACKENDFTRACEEVENT"]._serialized_start = 96149 + _globals["_DEVICEPMCALLBACKENDFTRACEEVENT"]._serialized_end = 96228 + _globals["_CONSOLEFTRACEEVENT"]._serialized_start = 96230 + _globals["_CONSOLEFTRACEEVENT"]._serialized_end = 96263 + _globals["_SYSENTERFTRACEEVENT"]._serialized_start = 96265 + _globals["_SYSENTERFTRACEEVENT"]._serialized_end = 96312 + _globals["_SYSEXITFTRACEEVENT"]._serialized_start = 96314 + _globals["_SYSEXITFTRACEEVENT"]._serialized_end = 96359 + _globals["_REGULATORDISABLEFTRACEEVENT"]._serialized_start = 96361 + _globals["_REGULATORDISABLEFTRACEEVENT"]._serialized_end = 96404 + _globals["_REGULATORDISABLECOMPLETEFTRACEEVENT"]._serialized_start = 96406 + _globals["_REGULATORDISABLECOMPLETEFTRACEEVENT"]._serialized_end = 96457 + _globals["_REGULATORENABLEFTRACEEVENT"]._serialized_start = 96459 + _globals["_REGULATORENABLEFTRACEEVENT"]._serialized_end = 96501 + _globals["_REGULATORENABLECOMPLETEFTRACEEVENT"]._serialized_start = 96503 + _globals["_REGULATORENABLECOMPLETEFTRACEEVENT"]._serialized_end = 96553 + _globals["_REGULATORENABLEDELAYFTRACEEVENT"]._serialized_start = 96555 + _globals["_REGULATORENABLEDELAYFTRACEEVENT"]._serialized_end = 96602 + _globals["_REGULATORSETVOLTAGEFTRACEEVENT"]._serialized_start = 96604 + _globals["_REGULATORSETVOLTAGEFTRACEEVENT"]._serialized_end = 96676 + _globals["_REGULATORSETVOLTAGECOMPLETEFTRACEEVENT"]._serialized_start = 96678 + _globals["_REGULATORSETVOLTAGECOMPLETEFTRACEEVENT"]._serialized_end = 96745 + _globals["_RPMSTATUSFTRACEEVENT"]._serialized_start = 96747 + _globals["_RPMSTATUSFTRACEEVENT"]._serialized_end = 96799 + _globals["_SAMSUNGTRACINGMARKWRITEFTRACEEVENT"]._serialized_start = 96801 + _globals["_SAMSUNGTRACINGMARKWRITEFTRACEEVENT"]._serialized_end = 96926 + _globals["_SCHEDSWITCHFTRACEEVENT"]._serialized_start = 96929 + _globals["_SCHEDSWITCHFTRACEEVENT"]._serialized_end = 97085 + _globals["_SCHEDWAKEUPFTRACEEVENT"]._serialized_start = 97087 + _globals["_SCHEDWAKEUPFTRACEEVENT"]._serialized_end = 97189 + _globals["_SCHEDBLOCKEDREASONFTRACEEVENT"]._serialized_start = 97191 + _globals["_SCHEDBLOCKEDREASONFTRACEEVENT"]._serialized_end = 97268 + _globals["_SCHEDCPUHOTPLUGFTRACEEVENT"]._serialized_start = 97270 + _globals["_SCHEDCPUHOTPLUGFTRACEEVENT"]._serialized_end = 97351 + _globals["_SCHEDWAKINGFTRACEEVENT"]._serialized_start = 97353 + _globals["_SCHEDWAKINGFTRACEEVENT"]._serialized_end = 97455 + _globals["_SCHEDWAKEUPNEWFTRACEEVENT"]._serialized_start = 97457 + _globals["_SCHEDWAKEUPNEWFTRACEEVENT"]._serialized_end = 97562 + _globals["_SCHEDPROCESSEXECFTRACEEVENT"]._serialized_start = 97564 + _globals["_SCHEDPROCESSEXECFTRACEEVENT"]._serialized_end = 97641 + _globals["_SCHEDPROCESSEXITFTRACEEVENT"]._serialized_start = 97643 + _globals["_SCHEDPROCESSEXITFTRACEEVENT"]._serialized_end = 97727 + _globals["_SCHEDPROCESSFORKFTRACEEVENT"]._serialized_start = 97729 + _globals["_SCHEDPROCESSFORKFTRACEEVENT"]._serialized_end = 97838 + _globals["_SCHEDPROCESSFREEFTRACEEVENT"]._serialized_start = 97840 + _globals["_SCHEDPROCESSFREEFTRACEEVENT"]._serialized_end = 97910 + _globals["_SCHEDPROCESSHANGFTRACEEVENT"]._serialized_start = 97912 + _globals["_SCHEDPROCESSHANGFTRACEEVENT"]._serialized_end = 97968 + _globals["_SCHEDPROCESSWAITFTRACEEVENT"]._serialized_start = 97970 + _globals["_SCHEDPROCESSWAITFTRACEEVENT"]._serialized_end = 98040 + _globals["_SCHEDPISETPRIOFTRACEEVENT"]._serialized_start = 98042 + _globals["_SCHEDPISETPRIOFTRACEEVENT"]._serialized_end = 98130 + _globals["_SCHEDCPUUTILCFSFTRACEEVENT"]._serialized_start = 98133 + _globals["_SCHEDCPUUTILCFSFTRACEEVENT"]._serialized_end = 98461 + _globals["_SCHEDMIGRATETASKFTRACEEVENT"]._serialized_start = 98464 + _globals["_SCHEDMIGRATETASKFTRACEEVENT"]._serialized_end = 98601 + _globals["_SCHEDWAKEUPTASKATTRFTRACEEVENT"]._serialized_start = 98603 + _globals["_SCHEDWAKEUPTASKATTRFTRACEEVENT"]._serialized_end = 98727 + _globals["_SCMCALLSTARTFTRACEEVENT"]._serialized_start = 98729 + _globals["_SCMCALLSTARTFTRACEEVENT"]._serialized_end = 98795 + _globals["_SCMCALLENDFTRACEEVENT"]._serialized_start = 98797 + _globals["_SCMCALLENDFTRACEEVENT"]._serialized_end = 98820 + _globals["_SDETRACINGMARKWRITEFTRACEEVENT"]._serialized_start = 98822 + _globals["_SDETRACINGMARKWRITEFTRACEEVENT"]._serialized_end = 98943 + _globals["_SDESDEEVTLOGFTRACEEVENT"]._serialized_start = 98945 + _globals["_SDESDEEVTLOGFTRACEEVENT"]._serialized_end = 99019 + _globals["_SDESDEPERFCALCCRTCFTRACEEVENT"]._serialized_start = 99022 + _globals["_SDESDEPERFCALCCRTCFTRACEEVENT"]._serialized_end = 99202 + _globals["_SDESDEPERFCRTCUPDATEFTRACEEVENT"]._serialized_start = 99205 + _globals["_SDESDEPERFCRTCUPDATEFTRACEEVENT"]._serialized_end = 99488 + _globals["_SDESDEPERFSETQOSLUTSFTRACEEVENT"]._serialized_start = 99490 + _globals["_SDESDEPERFSETQOSLUTSFTRACEEVENT"]._serialized_end = 99606 + _globals["_SDESDEPERFUPDATEBUSFTRACEEVENT"]._serialized_start = 99608 + _globals["_SDESDEPERFUPDATEBUSFTRACEEVENT"]._serialized_end = 99708 + _globals["_SIGNALDELIVERFTRACEEVENT"]._serialized_start = 99710 + _globals["_SIGNALDELIVERFTRACEEVENT"]._serialized_end = 99781 + _globals["_SIGNALGENERATEFTRACEEVENT"]._serialized_start = 99783 + _globals["_SIGNALGENERATEFTRACEEVENT"]._serialized_end = 99895 + _globals["_KFREESKBFTRACEEVENT"]._serialized_start = 99897 + _globals["_KFREESKBFTRACEEVENT"]._serialized_end = 99971 + _globals["_INETSOCKSETSTATEFTRACEEVENT"]._serialized_start = 99974 + _globals["_INETSOCKSETSTATEFTRACEEVENT"]._serialized_end = 100149 + _globals["_SYNCPTFTRACEEVENT"]._serialized_start = 100151 + _globals["_SYNCPTFTRACEEVENT"]._serialized_end = 100203 + _globals["_SYNCTIMELINEFTRACEEVENT"]._serialized_start = 100205 + _globals["_SYNCTIMELINEFTRACEEVENT"]._serialized_end = 100259 + _globals["_SYNCWAITFTRACEEVENT"]._serialized_start = 100261 + _globals["_SYNCWAITFTRACEEVENT"]._serialized_end = 100327 + _globals["_RSSSTATTHROTTLEDFTRACEEVENT"]._serialized_start = 100329 + _globals["_RSSSTATTHROTTLEDFTRACEEVENT"]._serialized_end = 100417 + _globals["_SUSPENDRESUMEMINIMALFTRACEEVENT"]._serialized_start = 100419 + _globals["_SUSPENDRESUMEMINIMALFTRACEEVENT"]._serialized_end = 100467 + _globals["_ZEROFTRACEEVENT"]._serialized_start = 100469 + _globals["_ZEROFTRACEEVENT"]._serialized_end = 100542 + _globals["_TASKNEWTASKFTRACEEVENT"]._serialized_start = 100544 + _globals["_TASKNEWTASKFTRACEEVENT"]._serialized_end = 100639 + _globals["_TASKRENAMEFTRACEEVENT"]._serialized_start = 100641 + _globals["_TASKRENAMEFTRACEEVENT"]._serialized_end = 100734 + _globals["_TCPRETRANSMITSKBFTRACEEVENT"]._serialized_start = 100737 + _globals["_TCPRETRANSMITSKBFTRACEEVENT"]._serialized_end = 100874 + _globals["_THERMALTEMPERATUREFTRACEEVENT"]._serialized_start = 100876 + _globals["_THERMALTEMPERATUREFTRACEEVENT"]._serialized_end = 100974 + _globals["_CDEVUPDATEFTRACEEVENT"]._serialized_start = 100976 + _globals["_CDEVUPDATEFTRACEEVENT"]._serialized_end = 101029 + _globals["_THERMALEXYNOSACPMBULKFTRACEEVENT"]._serialized_start = 101032 + _globals["_THERMALEXYNOSACPMBULKFTRACEEVENT"]._serialized_end = 101260 + _globals["_THERMALEXYNOSACPMHIGHOVERHEADFTRACEEVENT"]._serialized_start = 101263 + _globals["_THERMALEXYNOSACPMHIGHOVERHEADFTRACEEVENT"]._serialized_end = 101425 + _globals["_TRUSTYSMCFTRACEEVENT"]._serialized_start = 101427 + _globals["_TRUSTYSMCFTRACEEVENT"]._serialized_end = 101497 + _globals["_TRUSTYSMCDONEFTRACEEVENT"]._serialized_start = 101499 + _globals["_TRUSTYSMCDONEFTRACEEVENT"]._serialized_end = 101538 + _globals["_TRUSTYSTDCALL32FTRACEEVENT"]._serialized_start = 101540 + _globals["_TRUSTYSTDCALL32FTRACEEVENT"]._serialized_end = 101616 + _globals["_TRUSTYSTDCALL32DONEFTRACEEVENT"]._serialized_start = 101618 + _globals["_TRUSTYSTDCALL32DONEFTRACEEVENT"]._serialized_end = 101663 + _globals["_TRUSTYSHAREMEMORYFTRACEEVENT"]._serialized_start = 101665 + _globals["_TRUSTYSHAREMEMORYFTRACEEVENT"]._serialized_end = 101737 + _globals["_TRUSTYSHAREMEMORYDONEFTRACEEVENT"]._serialized_start = 101739 + _globals["_TRUSTYSHAREMEMORYDONEFTRACEEVENT"]._serialized_end = 101844 + _globals["_TRUSTYRECLAIMMEMORYFTRACEEVENT"]._serialized_start = 101846 + _globals["_TRUSTYRECLAIMMEMORYFTRACEEVENT"]._serialized_end = 101890 + _globals["_TRUSTYRECLAIMMEMORYDONEFTRACEEVENT"]._serialized_start = 101892 + _globals["_TRUSTYRECLAIMMEMORYDONEFTRACEEVENT"]._serialized_end = 101953 + _globals["_TRUSTYIRQFTRACEEVENT"]._serialized_start = 101955 + _globals["_TRUSTYIRQFTRACEEVENT"]._serialized_end = 101990 + _globals["_TRUSTYIPCHANDLEEVENTFTRACEEVENT"]._serialized_start = 101992 + _globals["_TRUSTYIPCHANDLEEVENTFTRACEEVENT"]._serialized_end = 102075 + _globals["_TRUSTYIPCCONNECTFTRACEEVENT"]._serialized_start = 102077 + _globals["_TRUSTYIPCCONNECTFTRACEEVENT"]._serialized_end = 102149 + _globals["_TRUSTYIPCCONNECTENDFTRACEEVENT"]._serialized_start = 102151 + _globals["_TRUSTYIPCCONNECTENDFTRACEEVENT"]._serialized_end = 102225 + _globals["_TRUSTYIPCWRITEFTRACEEVENT"]._serialized_start = 102228 + _globals["_TRUSTYIPCWRITEFTRACEEVENT"]._serialized_end = 102358 + _globals["_TRUSTYIPCPOLLFTRACEEVENT"]._serialized_start = 102360 + _globals["_TRUSTYIPCPOLLFTRACEEVENT"]._serialized_end = 102437 + _globals["_TRUSTYIPCREADFTRACEEVENT"]._serialized_start = 102439 + _globals["_TRUSTYIPCREADFTRACEEVENT"]._serialized_end = 102497 + _globals["_TRUSTYIPCREADENDFTRACEEVENT"]._serialized_start = 102499 + _globals["_TRUSTYIPCREADENDFTRACEEVENT"]._serialized_end = 102613 + _globals["_TRUSTYIPCRXFTRACEEVENT"]._serialized_start = 102615 + _globals["_TRUSTYIPCRXFTRACEEVENT"]._serialized_end = 102687 + _globals["_TRUSTYENQUEUENOPFTRACEEVENT"]._serialized_start = 102689 + _globals["_TRUSTYENQUEUENOPFTRACEEVENT"]._serialized_end = 102760 + _globals["_UFSHCDCOMMANDFTRACEEVENT"]._serialized_start = 102763 + _globals["_UFSHCDCOMMANDFTRACEEVENT"]._serialized_end = 102949 + _globals["_UFSHCDCLKGATINGFTRACEEVENT"]._serialized_start = 102951 + _globals["_UFSHCDCLKGATINGFTRACEEVENT"]._serialized_end = 103012 + _globals["_V4L2QBUFFTRACEEVENT"]._serialized_start = 103015 + _globals["_V4L2QBUFFTRACEEVENT"]._serialized_end = 103426 + _globals["_V4L2DQBUFFTRACEEVENT"]._serialized_start = 103429 + _globals["_V4L2DQBUFFTRACEEVENT"]._serialized_end = 103841 + _globals["_VB2V4L2BUFQUEUEFTRACEEVENT"]._serialized_start = 103844 + _globals["_VB2V4L2BUFQUEUEFTRACEEVENT"]._serialized_end = 104214 + _globals["_VB2V4L2BUFDONEFTRACEEVENT"]._serialized_start = 104217 + _globals["_VB2V4L2BUFDONEFTRACEEVENT"]._serialized_end = 104586 + _globals["_VB2V4L2QBUFFTRACEEVENT"]._serialized_start = 104589 + _globals["_VB2V4L2QBUFFTRACEEVENT"]._serialized_end = 104955 + _globals["_VB2V4L2DQBUFFTRACEEVENT"]._serialized_start = 104958 + _globals["_VB2V4L2DQBUFFTRACEEVENT"]._serialized_end = 105325 + _globals["_VIRTIOGPUCMDQUEUEFTRACEEVENT"]._serialized_start = 105328 + _globals["_VIRTIOGPUCMDQUEUEFTRACEEVENT"]._serialized_end = 105493 + _globals["_VIRTIOGPUCMDRESPONSEFTRACEEVENT"]._serialized_start = 105496 + _globals["_VIRTIOGPUCMDRESPONSEFTRACEEVENT"]._serialized_end = 105664 + _globals["_VIRTIOVIDEOCMDFTRACEEVENT"]._serialized_start = 105666 + _globals["_VIRTIOVIDEOCMDFTRACEEVENT"]._serialized_end = 105726 + _globals["_VIRTIOVIDEOCMDDONEFTRACEEVENT"]._serialized_start = 105728 + _globals["_VIRTIOVIDEOCMDDONEFTRACEEVENT"]._serialized_end = 105792 + _globals["_VIRTIOVIDEORESOURCEQUEUEFTRACEEVENT"]._serialized_start = 105795 + _globals["_VIRTIOVIDEORESOURCEQUEUEFTRACEEVENT"]._serialized_end = 105991 + _globals["_VIRTIOVIDEORESOURCEQUEUEDONEFTRACEEVENT"]._serialized_start = 105994 + _globals["_VIRTIOVIDEORESOURCEQUEUEDONEFTRACEEVENT"]._serialized_end = 106194 + _globals["_MMVMSCANDIRECTRECLAIMBEGINFTRACEEVENT"]._serialized_start = 106196 + _globals["_MMVMSCANDIRECTRECLAIMBEGINFTRACEEVENT"]._serialized_end = 106292 + _globals["_MMVMSCANDIRECTRECLAIMENDFTRACEEVENT"]._serialized_start = 106294 + _globals["_MMVMSCANDIRECTRECLAIMENDFTRACEEVENT"]._serialized_end = 106353 + _globals["_MMVMSCANKSWAPDWAKEFTRACEEVENT"]._serialized_start = 106355 + _globals["_MMVMSCANKSWAPDWAKEFTRACEEVENT"]._serialized_end = 106427 + _globals["_MMVMSCANKSWAPDSLEEPFTRACEEVENT"]._serialized_start = 106429 + _globals["_MMVMSCANKSWAPDSLEEPFTRACEEVENT"]._serialized_end = 106474 + _globals["_MMSHRINKSLABSTARTFTRACEEVENT"]._serialized_start = 106477 + _globals["_MMSHRINKSLABSTARTFTRACEEVENT"]._serialized_end = 106710 + _globals["_MMSHRINKSLABENDFTRACEEVENT"]._serialized_start = 106713 + _globals["_MMSHRINKSLABENDFTRACEEVENT"]._serialized_end = 106858 + _globals["_WORKQUEUEACTIVATEWORKFTRACEEVENT"]._serialized_start = 106860 + _globals["_WORKQUEUEACTIVATEWORKFTRACEEVENT"]._serialized_end = 106908 + _globals["_WORKQUEUEEXECUTEENDFTRACEEVENT"]._serialized_start = 106910 + _globals["_WORKQUEUEEXECUTEENDFTRACEEVENT"]._serialized_end = 106974 + _globals["_WORKQUEUEEXECUTESTARTFTRACEEVENT"]._serialized_start = 106976 + _globals["_WORKQUEUEEXECUTESTARTFTRACEEVENT"]._serialized_end = 107042 + _globals["_WORKQUEUEQUEUEWORKFTRACEEVENT"]._serialized_start = 107044 + _globals["_WORKQUEUEQUEUEWORKFTRACEEVENT"]._serialized_end = 107156 + _globals["_FTRACEEVENT"]._serialized_start = 107160 + _globals["_FTRACEEVENT"]._serialized_end = 147856 + _globals["_FTRACECPUSTATS"]._serialized_start = 147859 + _globals["_FTRACECPUSTATS"]._serialized_end = 148052 + _globals["_FTRACESTATS"]._serialized_start = 148055 + _globals["_FTRACESTATS"]._serialized_end = 148478 + _globals["_FTRACESTATS_PHASE"]._serialized_start = 148416 + _globals["_FTRACESTATS_PHASE"]._serialized_end = 148478 + _globals["_FTRACEEVENTBUNDLE"]._serialized_start = 148481 + _globals["_FTRACEEVENTBUNDLE"]._serialized_end = 149345 + _globals["_FTRACEEVENTBUNDLE_COMPACTSCHED"]._serialized_start = 148893 + _globals["_FTRACEEVENTBUNDLE_COMPACTSCHED"]._serialized_end = 149259 + _globals["_FTRACEEVENTBUNDLE_FTRACEERROR"]._serialized_start = 149261 + _globals["_FTRACEEVENTBUNDLE_FTRACEERROR"]._serialized_end = 149345 + _globals["_GPUCOUNTEREVENT"]._serialized_start = 149348 + _globals["_GPUCOUNTEREVENT"]._serialized_end = 149599 + _globals["_GPUCOUNTEREVENT_GPUCOUNTER"]._serialized_start = 149513 + _globals["_GPUCOUNTEREVENT_GPUCOUNTER"]._serialized_end = 149599 + _globals["_GPULOG"]._serialized_start = 149602 + _globals["_GPULOG"]._serialized_end = 149862 + _globals["_GPULOG_SEVERITY"]._serialized_start = 149699 + _globals["_GPULOG_SEVERITY"]._serialized_end = 149862 + _globals["_GPURENDERSTAGEEVENT"]._serialized_start = 149865 + _globals["_GPURENDERSTAGEEVENT"]._serialized_end = 150751 + _globals["_GPURENDERSTAGEEVENT_EXTRADATA"]._serialized_start = 150341 + _globals["_GPURENDERSTAGEEVENT_EXTRADATA"]._serialized_end = 150381 + _globals["_GPURENDERSTAGEEVENT_SPECIFICATIONS"]._serialized_start = 150384 + _globals["_GPURENDERSTAGEEVENT_SPECIFICATIONS"]._serialized_end = 150745 + _globals["_GPURENDERSTAGEEVENT_SPECIFICATIONS_CONTEXTSPEC"]._serialized_start = ( + 150652 + ) + _globals["_GPURENDERSTAGEEVENT_SPECIFICATIONS_CONTEXTSPEC"]._serialized_end = 150695 + _globals["_GPURENDERSTAGEEVENT_SPECIFICATIONS_DESCRIPTION"]._serialized_start = ( + 150697 + ) + _globals["_GPURENDERSTAGEEVENT_SPECIFICATIONS_DESCRIPTION"]._serialized_end = 150745 + _globals["_INTERNEDGRAPHICSCONTEXT"]._serialized_start = 150754 + _globals["_INTERNEDGRAPHICSCONTEXT"]._serialized_end = 150924 + _globals["_INTERNEDGRAPHICSCONTEXT_API"]._serialized_start = 150866 + _globals["_INTERNEDGRAPHICSCONTEXT_API"]._serialized_end = 150924 + _globals["_INTERNEDGPURENDERSTAGESPECIFICATION"]._serialized_start = 150927 + _globals["_INTERNEDGPURENDERSTAGESPECIFICATION"]._serialized_end = 151165 + _globals[ + "_INTERNEDGPURENDERSTAGESPECIFICATION_RENDERSTAGECATEGORY" + ]._serialized_start = 151106 + _globals[ + "_INTERNEDGPURENDERSTAGESPECIFICATION_RENDERSTAGECATEGORY" + ]._serialized_end = 151165 + _globals["_VULKANAPIEVENT"]._serialized_start = 151168 + _globals["_VULKANAPIEVENT"]._serialized_end = 151611 + _globals["_VULKANAPIEVENT_VKDEBUGUTILSOBJECTNAME"]._serialized_start = 151354 + _globals["_VULKANAPIEVENT_VKDEBUGUTILSOBJECTNAME"]._serialized_end = 151468 + _globals["_VULKANAPIEVENT_VKQUEUESUBMIT"]._serialized_start = 151471 + _globals["_VULKANAPIEVENT_VKQUEUESUBMIT"]._serialized_end = 151602 + _globals["_VULKANMEMORYEVENTANNOTATION"]._serialized_start = 151613 + _globals["_VULKANMEMORYEVENTANNOTATION"]._serialized_end = 151735 + _globals["_VULKANMEMORYEVENT"]._serialized_start = 151738 + _globals["_VULKANMEMORYEVENT"]._serialized_end = 152610 + _globals["_VULKANMEMORYEVENT_SOURCE"]._serialized_start = 152223 + _globals["_VULKANMEMORYEVENT_SOURCE"]._serialized_end = 152356 + _globals["_VULKANMEMORYEVENT_OPERATION"]._serialized_start = 152358 + _globals["_VULKANMEMORYEVENT_OPERATION"]._serialized_end = 152475 + _globals["_VULKANMEMORYEVENT_ALLOCATIONSCOPE"]._serialized_start = 152478 + _globals["_VULKANMEMORYEVENT_ALLOCATIONSCOPE"]._serialized_end = 152610 + _globals["_INTERNEDSTRING"]._serialized_start = 152612 + _globals["_INTERNEDSTRING"]._serialized_end = 152654 + _globals["_PROFILEDFRAMESYMBOLS"]._serialized_start = 152656 + _globals["_PROFILEDFRAMESYMBOLS"]._serialized_end = 152766 + _globals["_LINE"]._serialized_start = 152768 + _globals["_LINE"]._serialized_end = 152844 + _globals["_ADDRESSSYMBOLS"]._serialized_start = 152846 + _globals["_ADDRESSSYMBOLS"]._serialized_end = 152917 + _globals["_MODULESYMBOLS"]._serialized_start = 152919 + _globals["_MODULESYMBOLS"]._serialized_end = 153024 + _globals["_MAPPING"]._serialized_start = 153027 + _globals["_MAPPING"]._serialized_end = 153183 + _globals["_FRAME"]._serialized_start = 153185 + _globals["_FRAME"]._serialized_end = 153267 + _globals["_CALLSTACK"]._serialized_start = 153269 + _globals["_CALLSTACK"]._serialized_end = 153312 + _globals["_HISTOGRAMNAME"]._serialized_start = 153314 + _globals["_HISTOGRAMNAME"]._serialized_end = 153356 + _globals["_CHROMEHISTOGRAMSAMPLE"]._serialized_start = 153358 + _globals["_CHROMEHISTOGRAMSAMPLE"]._serialized_end = 153448 + _globals["_DEBUGANNOTATION"]._serialized_start = 153451 + _globals["_DEBUGANNOTATION"]._serialized_end = 154391 + _globals["_DEBUGANNOTATION_NESTEDVALUE"]._serialized_start = 153963 + _globals["_DEBUGANNOTATION_NESTEDVALUE"]._serialized_end = 154343 + _globals["_DEBUGANNOTATION_NESTEDVALUE_NESTEDTYPE"]._serialized_start = 154293 + _globals["_DEBUGANNOTATION_NESTEDVALUE_NESTEDTYPE"]._serialized_end = 154343 + _globals["_DEBUGANNOTATIONNAME"]._serialized_start = 154393 + _globals["_DEBUGANNOTATIONNAME"]._serialized_end = 154441 + _globals["_DEBUGANNOTATIONVALUETYPENAME"]._serialized_start = 154443 + _globals["_DEBUGANNOTATIONVALUETYPENAME"]._serialized_end = 154500 + _globals["_LOGMESSAGE"]._serialized_start = 154503 + _globals["_LOGMESSAGE"]._serialized_end = 154762 + _globals["_LOGMESSAGE_PRIORITY"]._serialized_start = 154617 + _globals["_LOGMESSAGE_PRIORITY"]._serialized_end = 154762 + _globals["_LOGMESSAGEBODY"]._serialized_start = 154764 + _globals["_LOGMESSAGEBODY"]._serialized_end = 154807 + _globals["_UNSYMBOLIZEDSOURCELOCATION"]._serialized_start = 154809 + _globals["_UNSYMBOLIZEDSOURCELOCATION"]._serialized_end = 154886 + _globals["_SOURCELOCATION"]._serialized_start = 154888 + _globals["_SOURCELOCATION"]._serialized_end = 154980 + _globals["_CHROMEACTIVEPROCESSES"]._serialized_start = 154982 + _globals["_CHROMEACTIVEPROCESSES"]._serialized_end = 155018 + _globals["_CHROMEAPPLICATIONSTATEINFO"]._serialized_start = 155021 + _globals["_CHROMEAPPLICATIONSTATEINFO"]._serialized_end = 155387 + _globals["_CHROMEAPPLICATIONSTATEINFO_CHROMEAPPLICATIONSTATE"]._serialized_start = ( + 155147 + ) + _globals["_CHROMEAPPLICATIONSTATEINFO_CHROMEAPPLICATIONSTATE"]._serialized_end = ( + 155387 + ) + _globals["_CHROMECOMPOSITORSCHEDULERSTATE"]._serialized_start = 155390 + _globals["_CHROMECOMPOSITORSCHEDULERSTATE"]._serialized_end = 156477 + _globals[ + "_CHROMECOMPOSITORSCHEDULERSTATE_BEGINIMPLFRAMEDEADLINEMODE" + ]._serialized_start = 156281 + _globals[ + "_CHROMECOMPOSITORSCHEDULERSTATE_BEGINIMPLFRAMEDEADLINEMODE" + ]._serialized_end = 156471 + _globals["_CHROMECOMPOSITORSTATEMACHINE"]._serialized_start = 156480 + _globals["_CHROMECOMPOSITORSTATEMACHINE"]._serialized_end = 160190 + _globals["_CHROMECOMPOSITORSTATEMACHINE_MAJORSTATE"]._serialized_start = 156671 + _globals["_CHROMECOMPOSITORSTATEMACHINE_MAJORSTATE"]._serialized_end = 157970 + _globals[ + "_CHROMECOMPOSITORSTATEMACHINE_MAJORSTATE_BEGINIMPLFRAMESTATE" + ]._serialized_start = 157210 + _globals[ + "_CHROMECOMPOSITORSTATEMACHINE_MAJORSTATE_BEGINIMPLFRAMESTATE" + ]._serialized_end = 157371 + _globals[ + "_CHROMECOMPOSITORSTATEMACHINE_MAJORSTATE_BEGINMAINFRAMESTATE" + ]._serialized_start = 157374 + _globals[ + "_CHROMECOMPOSITORSTATEMACHINE_MAJORSTATE_BEGINMAINFRAMESTATE" + ]._serialized_end = 157521 + _globals[ + "_CHROMECOMPOSITORSTATEMACHINE_MAJORSTATE_LAYERTREEFRAMESINKSTATE" + ]._serialized_start = 157524 + _globals[ + "_CHROMECOMPOSITORSTATEMACHINE_MAJORSTATE_LAYERTREEFRAMESINKSTATE" + ]._serialized_end = 157768 + _globals[ + "_CHROMECOMPOSITORSTATEMACHINE_MAJORSTATE_FORCEDREDRAWONTIMEOUTSTATE" + ]._serialized_start = 157771 + _globals[ + "_CHROMECOMPOSITORSTATEMACHINE_MAJORSTATE_FORCEDREDRAWONTIMEOUTSTATE" + ]._serialized_end = 157970 + _globals["_CHROMECOMPOSITORSTATEMACHINE_MINORSTATE"]._serialized_start = 157973 + _globals["_CHROMECOMPOSITORSTATEMACHINE_MINORSTATE"]._serialized_end = 160190 + _globals[ + "_CHROMECOMPOSITORSTATEMACHINE_MINORSTATE_TREEPRIORITY" + ]._serialized_start = 159867 + _globals[ + "_CHROMECOMPOSITORSTATEMACHINE_MINORSTATE_TREEPRIORITY" + ]._serialized_end = 160051 + _globals[ + "_CHROMECOMPOSITORSTATEMACHINE_MINORSTATE_SCROLLHANDLERSTATE" + ]._serialized_start = 160054 + _globals[ + "_CHROMECOMPOSITORSTATEMACHINE_MINORSTATE_SCROLLHANDLERSTATE" + ]._serialized_end = 160184 + _globals["_BEGINFRAMEARGS"]._serialized_start = 160193 + _globals["_BEGINFRAMEARGS"]._serialized_end = 160747 + _globals["_BEGINFRAMEARGS_BEGINFRAMEARGSTYPE"]._serialized_start = 160569 + _globals["_BEGINFRAMEARGS_BEGINFRAMEARGSTYPE"]._serialized_end = 160731 + _globals["_BEGINIMPLFRAMEARGS"]._serialized_start = 160750 + _globals["_BEGINIMPLFRAMEARGS"]._serialized_end = 161326 + _globals["_BEGINIMPLFRAMEARGS_TIMESTAMPSINUS"]._serialized_start = 161067 + _globals["_BEGINIMPLFRAMEARGS_TIMESTAMPSINUS"]._serialized_end = 161260 + _globals["_BEGINIMPLFRAMEARGS_STATE"]._serialized_start = 161262 + _globals["_BEGINIMPLFRAMEARGS_STATE"]._serialized_end = 161318 + _globals["_BEGINFRAMEOBSERVERSTATE"]._serialized_start = 161328 + _globals["_BEGINFRAMEOBSERVERSTATE"]._serialized_end = 161451 + _globals["_BEGINFRAMESOURCESTATE"]._serialized_start = 161454 + _globals["_BEGINFRAMESOURCESTATE"]._serialized_end = 161599 + _globals["_COMPOSITORTIMINGHISTORY"]._serialized_start = 161602 + _globals["_COMPOSITORTIMINGHISTORY"]._serialized_end = 161982 + _globals["_CHROMECONTENTSETTINGSEVENTINFO"]._serialized_start = 161984 + _globals["_CHROMECONTENTSETTINGSEVENTINFO"]._serialized_end = 162046 + _globals["_CHROMEFRAMEREPORTER"]._serialized_start = 162049 + _globals["_CHROMEFRAMEREPORTER"]._serialized_end = 163088 + _globals["_CHROMEFRAMEREPORTER_STATE"]._serialized_start = 162706 + _globals["_CHROMEFRAMEREPORTER_STATE"]._serialized_end = 162815 + _globals["_CHROMEFRAMEREPORTER_FRAMEDROPREASON"]._serialized_start = 162817 + _globals["_CHROMEFRAMEREPORTER_FRAMEDROPREASON"]._serialized_end = 162943 + _globals["_CHROMEFRAMEREPORTER_SCROLLSTATE"]._serialized_start = 162945 + _globals["_CHROMEFRAMEREPORTER_SCROLLSTATE"]._serialized_end = 163049 + _globals["_CHROMEFRAMEREPORTER_FRAMETYPE"]._serialized_start = 163051 + _globals["_CHROMEFRAMEREPORTER_FRAMETYPE"]._serialized_end = 163088 + _globals["_CHROMEKEYEDSERVICE"]._serialized_start = 163090 + _globals["_CHROMEKEYEDSERVICE"]._serialized_end = 163124 + _globals["_CHROMELATENCYINFO"]._serialized_start = 163127 + _globals["_CHROMELATENCYINFO"]._serialized_end = 164917 + _globals["_CHROMELATENCYINFO_COMPONENTINFO"]._serialized_start = 163456 + _globals["_CHROMELATENCYINFO_COMPONENTINFO"]._serialized_end = 163569 + _globals["_CHROMELATENCYINFO_STEP"]._serialized_start = 163572 + _globals["_CHROMELATENCYINFO_STEP"]._serialized_end = 163982 + _globals["_CHROMELATENCYINFO_LATENCYCOMPONENTTYPE"]._serialized_start = 163985 + _globals["_CHROMELATENCYINFO_LATENCYCOMPONENTTYPE"]._serialized_end = 164742 + _globals["_CHROMELATENCYINFO_INPUTTYPE"]._serialized_start = 164745 + _globals["_CHROMELATENCYINFO_INPUTTYPE"]._serialized_end = 164917 + _globals["_CHROMELEGACYIPC"]._serialized_start = 164920 + _globals["_CHROMELEGACYIPC"]._serialized_end = 165894 + _globals["_CHROMELEGACYIPC_MESSAGECLASS"]._serialized_start = 165032 + _globals["_CHROMELEGACYIPC_MESSAGECLASS"]._serialized_end = 165894 + _globals["_CHROMEMESSAGEPUMP"]._serialized_start = 165896 + _globals["_CHROMEMESSAGEPUMP"]._serialized_end = 165980 + _globals["_CHROMEMOJOEVENTINFO"]._serialized_start = 165983 + _globals["_CHROMEMOJOEVENTINFO"]._serialized_end = 166187 + _globals["_CHROMERENDERERSCHEDULERSTATE"]._serialized_start = 166189 + _globals["_CHROMERENDERERSCHEDULERSTATE"]._serialized_end = 166315 + _globals["_CHROMEUSEREVENT"]._serialized_start = 166317 + _globals["_CHROMEUSEREVENT"]._serialized_end = 166371 + _globals["_CHROMEWINDOWHANDLEEVENTINFO"]._serialized_start = 166373 + _globals["_CHROMEWINDOWHANDLEEVENTINFO"]._serialized_end = 166453 + _globals["_SCREENSHOT"]._serialized_start = 166455 + _globals["_SCREENSHOT"]._serialized_end = 166486 + _globals["_TASKEXECUTION"]._serialized_start = 166488 + _globals["_TASKEXECUTION"]._serialized_end = 166528 + _globals["_TRACKEVENT"]._serialized_start = 166531 + _globals["_TRACKEVENT"]._serialized_end = 169580 + _globals["_TRACKEVENT_LEGACYEVENT"]._serialized_start = 168626 + _globals["_TRACKEVENT_LEGACYEVENT"]._serialized_end = 169308 + _globals["_TRACKEVENT_LEGACYEVENT_FLOWDIRECTION"]._serialized_start = 169117 + _globals["_TRACKEVENT_LEGACYEVENT_FLOWDIRECTION"]._serialized_end = 169197 + _globals["_TRACKEVENT_LEGACYEVENT_INSTANTEVENTSCOPE"]._serialized_start = 169199 + _globals["_TRACKEVENT_LEGACYEVENT_INSTANTEVENTSCOPE"]._serialized_end = 169296 + _globals["_TRACKEVENT_TYPE"]._serialized_start = 169310 + _globals["_TRACKEVENT_TYPE"]._serialized_end = 169416 + _globals["_TRACKEVENTDEFAULTS"]._serialized_start = 169582 + _globals["_TRACKEVENTDEFAULTS"]._serialized_end = 169699 + _globals["_EVENTCATEGORY"]._serialized_start = 169701 + _globals["_EVENTCATEGORY"]._serialized_end = 169743 + _globals["_EVENTNAME"]._serialized_start = 169745 + _globals["_EVENTNAME"]._serialized_end = 169783 + _globals["_INTERNEDDATA"]._serialized_start = 169786 + _globals["_INTERNEDDATA"]._serialized_end = 171844 + _globals["_MEMORYTRACKERSNAPSHOT"]._serialized_start = 171847 + _globals["_MEMORYTRACKERSNAPSHOT"]._serialized_end = 172855 + _globals["_MEMORYTRACKERSNAPSHOT_PROCESSSNAPSHOT"]._serialized_start = 172062 + _globals["_MEMORYTRACKERSNAPSHOT_PROCESSSNAPSHOT"]._serialized_end = 172780 + _globals["_MEMORYTRACKERSNAPSHOT_PROCESSSNAPSHOT_MEMORYNODE"]._serialized_start = ( + 172276 + ) + _globals["_MEMORYTRACKERSNAPSHOT_PROCESSSNAPSHOT_MEMORYNODE"]._serialized_end = ( + 172687 + ) + _globals[ + "_MEMORYTRACKERSNAPSHOT_PROCESSSNAPSHOT_MEMORYNODE_MEMORYNODEENTRY" + ]._serialized_start = 172460 + _globals[ + "_MEMORYTRACKERSNAPSHOT_PROCESSSNAPSHOT_MEMORYNODE_MEMORYNODEENTRY" + ]._serialized_end = 172687 + _globals[ + "_MEMORYTRACKERSNAPSHOT_PROCESSSNAPSHOT_MEMORYNODE_MEMORYNODEENTRY_UNITS" + ]._serialized_start = 172641 + _globals[ + "_MEMORYTRACKERSNAPSHOT_PROCESSSNAPSHOT_MEMORYNODE_MEMORYNODEENTRY_UNITS" + ]._serialized_end = 172687 + _globals["_MEMORYTRACKERSNAPSHOT_PROCESSSNAPSHOT_MEMORYEDGE"]._serialized_start = ( + 172689 + ) + _globals["_MEMORYTRACKERSNAPSHOT_PROCESSSNAPSHOT_MEMORYEDGE"]._serialized_end = ( + 172780 + ) + _globals["_MEMORYTRACKERSNAPSHOT_LEVELOFDETAIL"]._serialized_start = 172782 + _globals["_MEMORYTRACKERSNAPSHOT_LEVELOFDETAIL"]._serialized_end = 172855 + _globals["_PERFETTOMETATRACE"]._serialized_start = 172858 + _globals["_PERFETTOMETATRACE"]._serialized_end = 173403 + _globals["_PERFETTOMETATRACE_ARG"]._serialized_start = 173215 + _globals["_PERFETTOMETATRACE_ARG"]._serialized_end = 173342 + _globals["_PERFETTOMETATRACE_INTERNEDSTRING"]._serialized_start = 173344 + _globals["_PERFETTOMETATRACE_INTERNEDSTRING"]._serialized_end = 173388 + _globals["_TRACINGSERVICEEVENT"]._serialized_start = 173406 + _globals["_TRACINGSERVICEEVENT"]._serialized_end = 173642 + _globals["_ANDROIDENERGYCONSUMER"]._serialized_start = 173644 + _globals["_ANDROIDENERGYCONSUMER"]._serialized_end = 173740 + _globals["_ANDROIDENERGYCONSUMERDESCRIPTOR"]._serialized_start = 173742 + _globals["_ANDROIDENERGYCONSUMERDESCRIPTOR"]._serialized_end = 173841 + _globals["_ANDROIDENERGYESTIMATIONBREAKDOWN"]._serialized_start = 173844 + _globals["_ANDROIDENERGYESTIMATIONBREAKDOWN"]._serialized_end = 174164 + _globals[ + "_ANDROIDENERGYESTIMATIONBREAKDOWN_ENERGYUIDBREAKDOWN" + ]._serialized_start = 174111 + _globals["_ANDROIDENERGYESTIMATIONBREAKDOWN_ENERGYUIDBREAKDOWN"]._serialized_end = ( + 174164 + ) + _globals["_ENTITYSTATERESIDENCY"]._serialized_start = 174167 + _globals["_ENTITYSTATERESIDENCY"]._serialized_end = 174610 + _globals["_ENTITYSTATERESIDENCY_POWERENTITYSTATE"]._serialized_start = 174348 + _globals["_ENTITYSTATERESIDENCY_POWERENTITYSTATE"]._serialized_end = 174450 + _globals["_ENTITYSTATERESIDENCY_STATERESIDENCY"]._serialized_start = 174453 + _globals["_ENTITYSTATERESIDENCY_STATERESIDENCY"]._serialized_end = 174610 + _globals["_BATTERYCOUNTERS"]._serialized_start = 174613 + _globals["_BATTERYCOUNTERS"]._serialized_end = 174790 + _globals["_POWERRAILS"]._serialized_start = 174793 + _globals["_POWERRAILS"]._serialized_end = 175098 + _globals["_POWERRAILS_RAILDESCRIPTOR"]._serialized_start = 174937 + _globals["_POWERRAILS_RAILDESCRIPTOR"]._serialized_end = 175031 + _globals["_POWERRAILS_ENERGYDATA"]._serialized_start = 175033 + _globals["_POWERRAILS_ENERGYDATA"]._serialized_end = 175098 + _globals["_OBFUSCATEDMEMBER"]._serialized_start = 175100 + _globals["_OBFUSCATEDMEMBER"]._serialized_end = 175170 + _globals["_OBFUSCATEDCLASS"]._serialized_start = 175173 + _globals["_OBFUSCATEDCLASS"]._serialized_end = 175368 + _globals["_DEOBFUSCATIONMAPPING"]._serialized_start = 175371 + _globals["_DEOBFUSCATIONMAPPING"]._serialized_end = 175499 + _globals["_HEAPGRAPHROOT"]._serialized_start = 175502 + _globals["_HEAPGRAPHROOT"]._serialized_end = 175940 + _globals["_HEAPGRAPHROOT_TYPE"]._serialized_start = 175600 + _globals["_HEAPGRAPHROOT_TYPE"]._serialized_end = 175940 + _globals["_HEAPGRAPHTYPE"]._serialized_start = 175943 + _globals["_HEAPGRAPHTYPE"]._serialized_end = 176427 + _globals["_HEAPGRAPHTYPE_KIND"]._serialized_start = 176165 + _globals["_HEAPGRAPHTYPE_KIND"]._serialized_end = 176427 + _globals["_HEAPGRAPHOBJECT"]._serialized_start = 176430 + _globals["_HEAPGRAPHOBJECT"]._serialized_end = 176676 + _globals["_HEAPGRAPH"]._serialized_start = 176679 + _globals["_HEAPGRAPH"]._serialized_end = 176999 + _globals["_PROFILEPACKET"]._serialized_start = 177002 + _globals["_PROFILEPACKET"]._serialized_end = 178470 + _globals["_PROFILEPACKET_HEAPSAMPLE"]._serialized_start = 177310 + _globals["_PROFILEPACKET_HEAPSAMPLE"]._serialized_end = 177496 + _globals["_PROFILEPACKET_HISTOGRAM"]._serialized_start = 177499 + _globals["_PROFILEPACKET_HISTOGRAM"]._serialized_end = 177642 + _globals["_PROFILEPACKET_HISTOGRAM_BUCKET"]._serialized_start = 177578 + _globals["_PROFILEPACKET_HISTOGRAM_BUCKET"]._serialized_end = 177642 + _globals["_PROFILEPACKET_PROCESSSTATS"]._serialized_start = 177645 + _globals["_PROFILEPACKET_PROCESSSTATS"]._serialized_end = 177867 + _globals["_PROFILEPACKET_PROCESSHEAPSAMPLES"]._serialized_start = 177870 + _globals["_PROFILEPACKET_PROCESSHEAPSAMPLES"]._serialized_end = 178470 + _globals["_PROFILEPACKET_PROCESSHEAPSAMPLES_CLIENTERROR"]._serialized_start = 178365 + _globals["_PROFILEPACKET_PROCESSHEAPSAMPLES_CLIENTERROR"]._serialized_end = 178470 + _globals["_STREAMINGALLOCATION"]._serialized_start = 178473 + _globals["_STREAMINGALLOCATION"]._serialized_end = 178630 + _globals["_STREAMINGFREE"]._serialized_start = 178632 + _globals["_STREAMINGFREE"]._serialized_end = 178706 + _globals["_STREAMINGPROFILEPACKET"]._serialized_start = 178708 + _globals["_STREAMINGPROFILEPACKET"]._serialized_end = 178809 + _globals["_PROFILING"]._serialized_start = 178812 + _globals["_PROFILING"]._serialized_end = 179468 + _globals["_PROFILING_CPUMODE"]._serialized_start = 178825 + _globals["_PROFILING_CPUMODE"]._serialized_end = 178949 + _globals["_PROFILING_STACKUNWINDERROR"]._serialized_start = 178952 + _globals["_PROFILING_STACKUNWINDERROR"]._serialized_end = 179468 + _globals["_PERFSAMPLE"]._serialized_start = 179471 + _globals["_PERFSAMPLE"]._serialized_end = 180293 + _globals["_PERFSAMPLE_PRODUCEREVENT"]._serialized_start = 179870 + _globals["_PERFSAMPLE_PRODUCEREVENT"]._serialized_end = 180090 + _globals["_PERFSAMPLE_PRODUCEREVENT_DATASOURCESTOPREASON"]._serialized_start = ( + 179981 + ) + _globals["_PERFSAMPLE_PRODUCEREVENT_DATASOURCESTOPREASON"]._serialized_end = 180059 + _globals["_PERFSAMPLE_SAMPLESKIPREASON"]._serialized_start = 180093 + _globals["_PERFSAMPLE_SAMPLESKIPREASON"]._serialized_end = 180234 + _globals["_PERFSAMPLEDEFAULTS"]._serialized_start = 180296 + _globals["_PERFSAMPLEDEFAULTS"]._serialized_end = 180431 + _globals["_SMAPSENTRY"]._serialized_start = 180434 + _globals["_SMAPSENTRY"]._serialized_end = 180821 + _globals["_SMAPSPACKET"]._serialized_start = 180823 + _globals["_SMAPSPACKET"]._serialized_end = 180895 + _globals["_PROCESSSTATS"]._serialized_start = 180898 + _globals["_PROCESSSTATS"]._serialized_end = 181702 + _globals["_PROCESSSTATS_THREAD"]._serialized_start = 181006 + _globals["_PROCESSSTATS_THREAD"]._serialized_end = 181045 + _globals["_PROCESSSTATS_FDINFO"]._serialized_start = 181047 + _globals["_PROCESSSTATS_FDINFO"]._serialized_end = 181081 + _globals["_PROCESSSTATS_PROCESS"]._serialized_start = 181084 + _globals["_PROCESSSTATS_PROCESS"]._serialized_end = 181702 + _globals["_PROCESSTREE"]._serialized_start = 181705 + _globals["_PROCESSTREE"]._serialized_end = 182051 + _globals["_PROCESSTREE_THREAD"]._serialized_start = 181865 + _globals["_PROCESSTREE_THREAD"]._serialized_end = 181929 + _globals["_PROCESSTREE_PROCESS"]._serialized_start = 181931 + _globals["_PROCESSTREE_PROCESS"]._serialized_end = 182051 + _globals["_REMOTECLOCKSYNC"]._serialized_start = 182054 + _globals["_REMOTECLOCKSYNC"]._serialized_end = 182265 + _globals["_REMOTECLOCKSYNC_SYNCEDCLOCKS"]._serialized_start = 182143 + _globals["_REMOTECLOCKSYNC_SYNCEDCLOCKS"]._serialized_end = 182265 + _globals["_ATOM"]._serialized_start = 182267 + _globals["_ATOM"]._serialized_end = 182273 + _globals["_STATSDATOM"]._serialized_start = 182275 + _globals["_STATSDATOM"]._serialized_end = 182349 + _globals["_SYSSTATS"]._serialized_start = 182352 + _globals["_SYSSTATS"]._serialized_end = 184358 + _globals["_SYSSTATS_MEMINFOVALUE"]._serialized_start = 183140 + _globals["_SYSSTATS_MEMINFOVALUE"]._serialized_end = 183216 + _globals["_SYSSTATS_VMSTATVALUE"]._serialized_start = 183218 + _globals["_SYSSTATS_VMSTATVALUE"]._serialized_end = 183292 + _globals["_SYSSTATS_CPUTIMES"]._serialized_start = 183295 + _globals["_SYSSTATS_CPUTIMES"]._serialized_end = 183457 + _globals["_SYSSTATS_INTERRUPTCOUNT"]._serialized_start = 183459 + _globals["_SYSSTATS_INTERRUPTCOUNT"]._serialized_end = 183503 + _globals["_SYSSTATS_DEVFREQVALUE"]._serialized_start = 183505 + _globals["_SYSSTATS_DEVFREQVALUE"]._serialized_end = 183547 + _globals["_SYSSTATS_BUDDYINFO"]._serialized_start = 183549 + _globals["_SYSSTATS_BUDDYINFO"]._serialized_end = 183609 + _globals["_SYSSTATS_DISKSTAT"]._serialized_start = 183612 + _globals["_SYSSTATS_DISKSTAT"]._serialized_end = 183827 + _globals["_SYSSTATS_PSISAMPLE"]._serialized_start = 183830 + _globals["_SYSSTATS_PSISAMPLE"]._serialized_end = 184138 + _globals["_SYSSTATS_PSISAMPLE_PSIRESOURCE"]._serialized_start = 183929 + _globals["_SYSSTATS_PSISAMPLE_PSIRESOURCE"]._serialized_end = 184138 + _globals["_SYSSTATS_THERMALZONE"]._serialized_start = 184140 + _globals["_SYSSTATS_THERMALZONE"]._serialized_end = 184195 + _globals["_SYSSTATS_CPUIDLESTATEENTRY"]._serialized_start = 184197 + _globals["_SYSSTATS_CPUIDLESTATEENTRY"]._serialized_end = 184252 + _globals["_SYSSTATS_CPUIDLESTATE"]._serialized_start = 184254 + _globals["_SYSSTATS_CPUIDLESTATE"]._serialized_end = 184358 + _globals["_UTSNAME"]._serialized_start = 184360 + _globals["_UTSNAME"]._serialized_end = 184437 + _globals["_SYSTEMINFO"]._serialized_start = 184440 + _globals["_SYSTEMINFO"]._serialized_end = 184788 + _globals["_CPUINFO"]._serialized_start = 184790 + _globals["_CPUINFO"]._serialized_end = 184908 + _globals["_CPUINFO_CPU"]._serialized_start = 184845 + _globals["_CPUINFO_CPU"]._serialized_end = 184908 + _globals["_TESTEVENT"]._serialized_start = 184911 + _globals["_TESTEVENT"]._serialized_end = 185290 + _globals["_TESTEVENT_TESTPAYLOAD"]._serialized_start = 185048 + _globals["_TESTEVENT_TESTPAYLOAD"]._serialized_end = 185290 + _globals["_TRACEPACKETDEFAULTS"]._serialized_start = 185293 + _globals["_TRACEPACKETDEFAULTS"]._serialized_end = 185535 + _globals["_TRACEUUID"]._serialized_start = 185537 + _globals["_TRACEUUID"]._serialized_end = 185574 + _globals["_PROCESSDESCRIPTOR"]._serialized_start = 185577 + _globals["_PROCESSDESCRIPTOR"]._serialized_end = 186064 + _globals["_PROCESSDESCRIPTOR_CHROMEPROCESSTYPE"]._serialized_start = 185839 + _globals["_PROCESSDESCRIPTOR_CHROMEPROCESSTYPE"]._serialized_end = 186064 + _globals["_TRACKEVENTRANGEOFINTEREST"]._serialized_start = 186066 + _globals["_TRACKEVENTRANGEOFINTEREST"]._serialized_end = 186111 + _globals["_THREADDESCRIPTOR"]._serialized_start = 186114 + _globals["_THREADDESCRIPTOR"]._serialized_end = 186870 + _globals["_THREADDESCRIPTOR_CHROMETHREADTYPE"]._serialized_start = 186399 + _globals["_THREADDESCRIPTOR_CHROMETHREADTYPE"]._serialized_end = 186870 + _globals["_CHROMEPROCESSDESCRIPTOR"]._serialized_start = 186873 + _globals["_CHROMEPROCESSDESCRIPTOR"]._serialized_end = 188382 + _globals["_CHROMEPROCESSDESCRIPTOR_PROCESSTYPE"]._serialized_start = 187085 + _globals["_CHROMEPROCESSDESCRIPTOR_PROCESSTYPE"]._serialized_end = 188382 + _globals["_CHROMETHREADDESCRIPTOR"]._serialized_start = 188385 + _globals["_CHROMETHREADDESCRIPTOR"]._serialized_end = 189645 + _globals["_CHROMETHREADDESCRIPTOR_THREADTYPE"]._serialized_start = 188512 + _globals["_CHROMETHREADDESCRIPTOR_THREADTYPE"]._serialized_end = 189645 + _globals["_COUNTERDESCRIPTOR"]._serialized_start = 189648 + _globals["_COUNTERDESCRIPTOR"]._serialized_end = 190077 + _globals["_COUNTERDESCRIPTOR_BUILTINCOUNTERTYPE"]._serialized_start = 189881 + _globals["_COUNTERDESCRIPTOR_BUILTINCOUNTERTYPE"]._serialized_end = 189992 + _globals["_COUNTERDESCRIPTOR_UNIT"]._serialized_start = 189994 + _globals["_COUNTERDESCRIPTOR_UNIT"]._serialized_end = 190077 + _globals["_TRACKDESCRIPTOR"]._serialized_start = 190080 + _globals["_TRACKDESCRIPTOR"]._serialized_end = 190529 + _globals["_TRANSLATIONTABLE"]._serialized_start = 190532 + _globals["_TRANSLATIONTABLE"]._serialized_end = 190955 + _globals["_CHROMEHISTORGRAMTRANSLATIONTABLE"]._serialized_start = 190958 + _globals["_CHROMEHISTORGRAMTRANSLATIONTABLE"]._serialized_end = 191132 + _globals["_CHROMEHISTORGRAMTRANSLATIONTABLE_HASHTONAMEENTRY"]._serialized_start = ( + 191083 + ) + _globals["_CHROMEHISTORGRAMTRANSLATIONTABLE_HASHTONAMEENTRY"]._serialized_end = ( + 191132 + ) + _globals["_CHROMEUSEREVENTTRANSLATIONTABLE"]._serialized_start = 191135 + _globals["_CHROMEUSEREVENTTRANSLATIONTABLE"]._serialized_end = 191326 + _globals[ + "_CHROMEUSEREVENTTRANSLATIONTABLE_ACTIONHASHTONAMEENTRY" + ]._serialized_start = 191271 + _globals[ + "_CHROMEUSEREVENTTRANSLATIONTABLE_ACTIONHASHTONAMEENTRY" + ]._serialized_end = 191326 + _globals["_CHROMEPERFORMANCEMARKTRANSLATIONTABLE"]._serialized_start = 191329 + _globals["_CHROMEPERFORMANCEMARKTRANSLATIONTABLE"]._serialized_end = 191684 + _globals[ + "_CHROMEPERFORMANCEMARKTRANSLATIONTABLE_SITEHASHTONAMEENTRY" + ]._serialized_start = 191576 + _globals[ + "_CHROMEPERFORMANCEMARKTRANSLATIONTABLE_SITEHASHTONAMEENTRY" + ]._serialized_end = 191629 + _globals[ + "_CHROMEPERFORMANCEMARKTRANSLATIONTABLE_MARKHASHTONAMEENTRY" + ]._serialized_start = 191631 + _globals[ + "_CHROMEPERFORMANCEMARKTRANSLATIONTABLE_MARKHASHTONAMEENTRY" + ]._serialized_end = 191684 + _globals["_SLICENAMETRANSLATIONTABLE"]._serialized_start = 191687 + _globals["_SLICENAMETRANSLATIONTABLE"]._serialized_end = 191881 + _globals[ + "_SLICENAMETRANSLATIONTABLE_RAWTODEOBFUSCATEDNAMEENTRY" + ]._serialized_start = 191821 + _globals[ + "_SLICENAMETRANSLATIONTABLE_RAWTODEOBFUSCATEDNAMEENTRY" + ]._serialized_end = 191881 + _globals["_PROCESSTRACKNAMETRANSLATIONTABLE"]._serialized_start = 191884 + _globals["_PROCESSTRACKNAMETRANSLATIONTABLE"]._serialized_end = 192092 + _globals[ + "_PROCESSTRACKNAMETRANSLATIONTABLE_RAWTODEOBFUSCATEDNAMEENTRY" + ]._serialized_start = 191821 + _globals[ + "_PROCESSTRACKNAMETRANSLATIONTABLE_RAWTODEOBFUSCATEDNAMEENTRY" + ]._serialized_end = 191881 + _globals["_TRIGGER"]._serialized_start = 192094 + _globals["_TRIGGER"]._serialized_end = 192178 + _globals["_UISTATE"]._serialized_start = 192181 + _globals["_UISTATE"]._serialized_end = 192378 + _globals["_UISTATE_HIGHLIGHTPROCESS"]._serialized_start = 192314 + _globals["_UISTATE_HIGHLIGHTPROCESS"]._serialized_end = 192378 + _globals["_TRACEPACKET"]._serialized_start = 192381 + _globals["_TRACEPACKET"]._serialized_end = 197901 + _globals["_TRACEPACKET_SEQUENCEFLAGS"]._serialized_start = 197720 + _globals["_TRACEPACKET_SEQUENCEFLAGS"]._serialized_end = 197824 + _globals["_TRACE"]._serialized_start = 197903 + _globals["_TRACE"]._serialized_end = 197956 +# @@protoc_insertion_point(module_scope) diff --git a/tools/pynuttx/nxtrace/trace.py b/tools/pynuttx/nxtrace/trace.py new file mode 100644 index 00000000000..21d93105d06 --- /dev/null +++ b/tools/pynuttx/nxtrace/trace.py @@ -0,0 +1,313 @@ +############################################################################ +# tools/pynuttx/nxtrace/trace.py +# +# Licensed to the Apache Software Foundation (ASF) under one or more +# contributor license agreements. See the NOTICE file distributed with +# this work for additional information regarding copyright ownership. The +# ASF licenses this file to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance with the +# License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# +############################################################################ + +import logging +import sys + +from .perfetto_trace import PerfettoTrace, TaskInfo, TaskState, TraceHead + +try: + from construct import Adapter, Bytes, Container, CString, Struct, this +except ModuleNotFoundError: + print("Please execute the following command to install dependencies:") + print("pip install construct") + exit(1) + +logger = logging.getLogger(__name__) +logger.setLevel(logging.WARN) + +# Corresponds to the tstate_e enumeration type in nuttx + +Tstate = None + + +class TaskNameCache: + _instances = {} + + def __new__(cls, pid, name): + cls._instances.setdefault(pid, name) + return cls._instances[pid] + + @classmethod + def find(cls, pid): + return cls._instances.get(pid, "unknown") + + +class StringAdapter(Adapter): + def _decode(self, obj, context, path): + name = obj.split(b"\0", 1)[0].decode("utf-8") + return name + + def _encode(self, obj, context, path): + return obj.encode("utf-8") + b"\0" + + +def Tstate2State(state): + if state == Tstate.TSTATE_TASK_INVALID: + return TaskState.DEAD + elif state <= Tstate.TSTATE_TASK_RUNNING: + return TaskState.RUNNING + else: + return TaskState.INTERRUPTIBLE + + +def GenTraceHead(note): + return TraceHead(note.nc_systime, note.nc_pid, note.nc_cpu) + + +class NoteFactory: + instance = None + parser = None + types = None + mapping = dict() + type2name = dict() + + def __new__(cls, elf_parser): + if cls.instance is None: + cls.instance = super().__new__(cls) + cls.instance.parser = elf_parser + cls.init_instance(elf_parser) + return cls.instance + + @classmethod + def init_instance(cls, elf_parser, output): + if elf_parser is None: + raise TypeError("Value of 'elf_parser' cannot be None") + + cls.parser = elf_parser + cls.ptrace = PerfettoTrace(output) + cls.NCPUS = elf_parser.macro("CONFIG_SMP_NCPUS") + cls.types = elf_parser.enum("note_type_e") + global Tstate + Tstate = elf_parser.enum("tstate_e") + + cls.mapping = { + "note_common_s": cls.parser.get_type("note_common_s"), + "note_event_s": Struct( + "nev_cmn" / cls.parser.get_type("note_common_s"), + "nev_data" + / Bytes(this.length - cls.parser.get_type("note_common_s").sizeof()), + ), + } + + try: + cls.type2name = { + cls.types.NOTE_STOP: "note_stop_s", + cls.types.NOTE_SUSPEND: "note_suspend_s", + cls.types.NOTE_RESUME: "note_resume_s", + cls.types.NOTE_SYSCALL_ENTER: "note_syscall_enter_s", + cls.types.NOTE_SYSCALL_LEAVE: "note_syscall_leave_s", + cls.types.NOTE_IRQ_ENTER: "note_irqhandler_s", + cls.types.NOTE_IRQ_LEAVE: "note_irqhandler_s", + cls.types.NOTE_DUMP_PRINTF: "note_printf_s", + cls.types.NOTE_DUMP_BEGIN: "note_event_s", + cls.types.NOTE_DUMP_END: "note_event_s", + cls.types.NOTE_DUMP_MARK: "note_event_s", + } + except Exception as e: + logger.error(f"Error initializing NoteFactory: {e}") + exit(1) + + @classmethod + def struct(cls, note_type): + if note_type in cls.mapping: + return cls.mapping[note_type] + + if note_type in cls.type2name: + struct = cls.parser.get_type(cls.type2name[note_type]) + elif note_type == cls.types.NOTE_START: + struct = Struct( + "nst_cmn" / cls.mapping["note_common_s"], + "name" / CString("utf8"), + ) + elif note_type == cls.types.NOTE_DUMP_COUNTER: + struct = cls.mapping["note_event_s"] + cls.parser.get_type("note_counter_s") + elif note_type == cls.types.NOTE_DUMP_THREADTIME: + struct = cls.mapping["note_event_s"] + cls.parser.get_type( + "note_threadtime_s" + ) + else: + raise ValueError(f"Unknown note type: {note_type}") + + cls.mapping[note_type] = struct + return struct + + @classmethod + def parse(cls, data): + if len(data) < 4 or len(data) < data[0]: + return None + + note_length = data[0] + note_type = data[1] + cpu = data[3] + + if note_type >= len(cls.types): + raise ValueError(f"Unknown note type: {note_type}") + + if note_length > 256: + raise ValueError(f"Note length not valid: {note_length}") + + if cpu >= cls.NCPUS: + raise ValueError(f"CPU number too large: {cpu}") + + struct = cls.struct(note_type) + note = struct.parse(data[:note_length]) + logger.debug(note) + + class Note(Container): + def __getattr__(self, name): + if name not in self.keys(): + for key in self.keys(): + if isinstance(self[key], Container): + return getattr(self[key], name) + return self[name] + + return Note(note) + + @classmethod + def dump(cls, notes=None, output="trace.perfetto"): + sched_switch = { + "intr_nest": 0, + "pendingswitch": False, + "current_pid": -1, + "current_priority": -1, + "current_state": -1, + "next_pid": -1, + "next_priority": -1, + } + + for note in notes: + logger.debug(note) + head = GenTraceHead(note) + + if note.nc_type == cls.types.NOTE_START: + TaskNameCache(note.nc_pid, note.name) + task = TaskInfo(note.name, note.nc_pid, note.nc_priority) + cls.ptrace.sched_wakeup_new(head, task) + elif note.nc_type == cls.types.NOTE_STOP: + sched_switch["current_state"] = Tstate.TSTATE_TASK_INVALID + elif note.nc_type == cls.types.NOTE_SUSPEND: + sched_switch["current_state"] = note.nsu_state + elif note.nc_type == cls.types.NOTE_RESUME: + sched_switch["next_pid"] = note.nc_pid + sched_switch["next_priority"] = note.nc_priority + + # If we are in an interrupt, we need to wake up and suspend the task + if sched_switch["intr_nest"]: + current = TaskInfo( + TaskNameCache.find(note.nc_pid), note.nc_pid, note.nc_priority + ) + sched_switch["pendingswitch"] = True + cls.ptrace.sched_waking(head, current) + else: + # If there is no interrupt, we need to switch the task + prev = TaskInfo( + TaskNameCache.find(sched_switch["current_pid"]), + sched_switch["current_pid"], + sched_switch["current_priority"], + ) + next = TaskInfo( + TaskNameCache.find(sched_switch["next_pid"]), + sched_switch["next_pid"], + sched_switch["next_priority"], + ) + state = Tstate2State(sched_switch["current_state"]) + cls.ptrace.sched_switch(head, state, prev, next) + sched_switch["current_pid"] = sched_switch["next_pid"] + sched_switch["current_priority"] = sched_switch["next_priority"] + elif note.nc_type == cls.types.NOTE_IRQ_ENTER: + sched_switch["intr_nest"] += 1 + cls.ptrace.irq_entry( + head, note.nih_irq, f"{note.nih_irq}, {note.nih_handler}", 0 + ) + elif note.nc_type == cls.types.NOTE_IRQ_LEAVE: + sched_switch["intr_nest"] -= 1 + cls.ptrace.irq_exit(head, note.nih_irq, 0) + + if sched_switch["pendingswitch"]: + # If there is a suspended task, perform task switching when the interrupt exits + state = Tstate2State(sched_switch["current_state"]) + prev = TaskInfo( + TaskNameCache.find(sched_switch["current_pid"]), + sched_switch["current_pid"], + sched_switch["current_priority"], + ) + next = TaskInfo( + TaskNameCache.find(sched_switch["next_pid"]), + sched_switch["next_pid"], + sched_switch["next_priority"], + ) + cls.ptrace.sched_switch(head, state, prev, next) + sched_switch["pendingswitch"] = False + sched_switch["current_pid"] = sched_switch["next_pid"] + sched_switch["current_priority"] = sched_switch["next_priority"] + + logger.debug(sched_switch) + + @classmethod + def flush(cls): + cls.ptrace.flush() + + +class NoteParser: + + def __init__(self, parser, cache_size=0, output=None): + self.notes = list() + self.cache_size = cache_size + self.buffer = bytearray() + self.parser = parser + self.output = output + NoteFactory.init_instance(parser, output) + + def dump(self, notes=None): + output = self.output if self.output is sys.stdout else "trace.perfetto" + notes = self.notes if notes is None else notes + NoteFactory.dump(notes, output) + + def flush(self): + NoteFactory.flush() + print(f"note parser flush to file: {self.output}") + + def parse(self, data): + self.buffer.extend(data) + notes = list() + while len(self.buffer): + try: + note = NoteFactory.parse(self.buffer) + except Exception as e: + logger.error(f"skip bytes: {self.buffer[0]} {e}") + self.buffer = self.buffer[1:] + continue + + if note is None: + break + + notes.append(note) + self.notes.append(note) + self.buffer = self.buffer[note.nc_length :] + if self.cache_size > 0 and len(notes) >= self.cache_size: + self.notes.pop(0) + + return notes + + def parse_file(self, path): + with open(path, "rb") as f: + data = f.read() + self.parse(data) diff --git a/tools/pynuttx/requirements.txt b/tools/pynuttx/requirements.txt index 0aed2fa4777..f7c3af36452 100644 --- a/tools/pynuttx/requirements.txt +++ b/tools/pynuttx/requirements.txt @@ -1,3 +1,4 @@ +construct==2.10.70 contourpy==1.3.0 cycler==0.12.1 debugpy==1.8.7 @@ -7,6 +8,7 @@ matplotlib==3.9.2 numpy==2.1.2 packaging==24.1 pillow==11.0.0 +protobuf==4.25.3 pyelftools==0.31 pyparsing==3.2.0 python-dateutil==2.9.0.post0 diff --git a/tools/pynuttx/traceparse.py b/tools/pynuttx/traceparse.py new file mode 100644 index 00000000000..5aa92ec668a --- /dev/null +++ b/tools/pynuttx/traceparse.py @@ -0,0 +1,37 @@ +#!/usr/bin/env python3 +############################################################################ +# tools/pynuttx/traceparse.py +# +# Licensed to the Apache Software Foundation (ASF) under one or more +# contributor license agreements. See the NOTICE file distributed with +# this work for additional information regarding copyright ownership. The +# ASF licenses this file to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance with the +# License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# +############################################################################ + +import argparse + +from nxelf.elf import ELFParser +from nxtrace.trace import NoteParser + +if __name__ == "__main__": + parser = argparse.ArgumentParser() + parser.add_argument("-e", "--elf", help="ELF file", required=True) + parser.add_argument("-b", "--binary", help="Binary note file", required=True) + parser.add_argument("-o", "--output", help="Output file") + args = parser.parse_args() + + elf_parser = ELFParser(args.elf) + note_parser = NoteParser(elf_parser, output=args.output) + note_parser.parse_file(args.binary) + note_parser.dump() -- Gitee From 12ae92c241bd8c7c574d34b21e25403edf6429d0 Mon Sep 17 00:00:00 2001 From: yinshengkai Date: Mon, 16 Dec 2024 20:30:52 +0800 Subject: [PATCH 044/235] tools/pynuttx: Add rtt data reading script VELAPLATFO-48894 Change-Id: I48e6d1348d7e60f705ef1db9a40accdd9b94c278 Signed-off-by: yinshengkai --- tools/pynuttx/nxtrace/rtt.py | 144 +++++++++++++++++++++++++++++++++++ tools/pynuttx/traceparse.py | 98 ++++++++++++++++++++++-- 2 files changed, 235 insertions(+), 7 deletions(-) create mode 100644 tools/pynuttx/nxtrace/rtt.py diff --git a/tools/pynuttx/nxtrace/rtt.py b/tools/pynuttx/nxtrace/rtt.py new file mode 100644 index 00000000000..b9e518e4a13 --- /dev/null +++ b/tools/pynuttx/nxtrace/rtt.py @@ -0,0 +1,144 @@ +############################################################################ +# tools/pynuttx/nxtrace/rtt.py +# +# Licensed to the Apache Software Foundation (ASF) under one or more +# contributor license agreements. See the NOTICE file distributed with +# this work for additional information regarding copyright ownership. The +# ASF licenses this file to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance with the +# License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# +############################################################################ + +import logging +import os +import subprocess +import threading +import time + +logger = logging.getLogger(__name__) +logger.setLevel(logging.WARN) + + +class SeggerRTT: + def __init__( + self, + device, + interface, + address=None, + speed=None, + channel=None, + ): + self.receive_total = 0 + self.receive_rate = 0 + + # Check if the JLinkRTTLogger command exists + if not any( + os.access(os.path.join(path, "JLinkRTTLogger"), os.X_OK) + for path in os.environ["PATH"].split(os.pathsep) + ): + raise RuntimeError( + "JLinkRTTLogger command not found, please ensure SEGGER JLink software is installed" + ) + + if channel is None: + channel = 0 + if speed is None: + speed = 16000 + + # Create a named pipe + self.pipe = f"/tmp/jlink_rtt_pipe_{channel}" + if not os.path.exists(self.pipe): + os.mkfifo(self.pipe) + + # Start the JLinkRTTLogger process + cmd = [ + "JLinkRTTLogger", + "-If", + interface, + "-device", + device, + "-RTTChannel", + f"{channel}", + "-Speed", + f"{speed}", + ] + + if address is not None: + cmd.append("-RTTAddress") + cmd.append(f"0x{address:x}") + + cmd.append(self.pipe) + self.running = False + self.buffer = bytearray() + self.condition = threading.Condition() + print(f"Starting JLinkRTTLogger with command: {cmd}") + self.jlink_process = subprocess.Popen(cmd) + self.thread = threading.Thread(target=self.process_data, daemon=True) + + def __del__(self): + if self.running: + self.stop() + + def process_data(self): + last_receive_total = 0 + last_time = time.time() + + # Independent thread receives data to avoid data loss + with open(self.pipe, "rb") as f: + while self.running: + data = f.read1() + + if data is None: + continue + + if time.time() - last_time > 0.5: + now_time = time.time() + self.receive_rate = (self.receive_total - last_receive_total) / ( + now_time - last_time + ) + last_time = now_time + last_receive_total = self.receive_total + logger.debug( + f"Receive rate: {self.receive_rate/1024:.2f} KB/s, total: {self.receive_total/1024/1024:.2f} MB" + ) + self.receive_total += len(data) + + # Notify the waiting thread that data is available + with self.condition: + self.buffer.extend(data) + self.condition.notify() + + def read(self, size=1024): + try: + with self.condition: + while not self.buffer: + # Wait for data to be available + self.condition.wait() + + data = bytes(self.buffer[:size]) + self.buffer = self.buffer[size:] + return data + except Exception as e: + logger.error(f"Error reading data: {e}") + exit(1) + + def start(self): + if self.jlink_process.poll() is not None: + logger.error("Failed to start JLinkRTTLogger process") + raise RuntimeError("Failed to start JLinkRTTLogger process") + self.running = True + self.thread.start() + + def stop(self): + self.running = False + self.thread.join() + os.unlink(self.pipe) diff --git a/tools/pynuttx/traceparse.py b/tools/pynuttx/traceparse.py index 5aa92ec668a..e483949c28f 100644 --- a/tools/pynuttx/traceparse.py +++ b/tools/pynuttx/traceparse.py @@ -20,18 +20,102 @@ ############################################################################ import argparse +import signal +import sys from nxelf.elf import ELFParser +from nxtrace.rtt import SeggerRTT from nxtrace.trace import NoteParser -if __name__ == "__main__": + +def note_binary_parser(elf_parser, note_parser, binary_file): + note_parser.parse_file(binary_file) + note_parser.dump() + + +def rtt_parser(elf_parser, note_parser, device, interface, speed, channel): + # Get the address of the _SEGGER_RTT symbol + address = elf_parser.symbol_addr("_SEGGER_RTT") + running = True + if address is None: + raise RuntimeError( + "Symbol _SEGGER_RTT not found, please check if the ELF is correct or if SEGGER RTT is enabled" + ) + + rtt = SeggerRTT( + device, + interface, + speed=speed, + channel=channel, + address=address, + ) + + def signal_handler(signum, frame): + nonlocal running + if running: + print("\nReceived signal\n") + running = False + rtt.stop() + note_parser.flush() + sys.exit(0) + else: + print("Already received signal, exiting...") + sys.exit(0) + + signal.signal(signal.SIGINT, signal_handler) + signal.signal(signal.SIGTERM, signal_handler) + + rtt.start() + print("Starting RTT...") + while running: + data = rtt.read() + if not data: + continue + + notes = note_parser.parse(data) + note_parser.dump(notes) + + +def arg_parse(): parser = argparse.ArgumentParser() parser.add_argument("-e", "--elf", help="ELF file", required=True) - parser.add_argument("-b", "--binary", help="Binary note file", required=True) - parser.add_argument("-o", "--output", help="Output file") + parser.add_argument("-o", "--output", help="Output file", default="trace.perfetto") + parser.add_argument("-b", "--binary", help="Binary note file") + parser.add_argument("-d", "--device", help="RTT device") + parser.add_argument("-i", "--interface", help="RTT interface") + parser.add_argument("-s", "--speed", type=int, help="RTT speed") + parser.add_argument("-c", "--channel", type=int, help="RTT channel") args = parser.parse_args() - elf_parser = ELFParser(args.elf) - note_parser = NoteParser(elf_parser, output=args.output) - note_parser.parse_file(args.binary) - note_parser.dump() + # Validate the arguments + if args.binary: + return vars(args) + elif args.device and args.interface: + return vars(args) + elif args.device or args.interface: + print("Error: Both --device and --interface must be specified together.") + sys.exit(1) + else: + print( + "Error: You must specify either a binary file or both RTT parameters (--device and --interface)." + ) + sys.exit(1) + + +if __name__ == "__main__": + args = arg_parse() + + elf_parser = ELFParser(args["elf"]) + note_parser = NoteParser(elf_parser, output=args["output"]) + + if args.get("binary"): + note_binary_parser(elf_parser, note_parser, args["binary"]) + elif args.get("device"): + rtt_parser( + elf_parser, + note_parser, + args["device"], + args["interface"], + args.get("speed"), + args.get("channel"), + ) -- Gitee From ea46be6ac66cf83a89b7af7720142c384485d35e Mon Sep 17 00:00:00 2001 From: xuxingliang Date: Fri, 20 Dec 2024 20:07:31 +0800 Subject: [PATCH 045/235] nxgdb/mm: warning if corrupted memory node found VELAPLATFO-48924 If the nodesize is 0, we cannot iterate to next node, siliently return None will cause memleak command to generate false positive report with no warnings. Add log to indicate such case. Change-Id: I69d9831ac0afe0c89f8d20e361960b6306b659c9 Signed-off-by: xuxingliang --- tools/pynuttx/nxgdb/mm.py | 1 + 1 file changed, 1 insertion(+) diff --git a/tools/pynuttx/nxgdb/mm.py b/tools/pynuttx/nxgdb/mm.py index 05b94e1eb00..7ec814164d6 100644 --- a/tools/pynuttx/nxgdb/mm.py +++ b/tools/pynuttx/nxgdb/mm.py @@ -483,6 +483,7 @@ class MMNode(gdb.Value, p.MMFreeNode): @property def nextnode(self) -> MMNode: if not self.nodesize: + gdb.write(f"\n\x1b[31;1m Node corrupted: {self} \x1b[m\n") return None addr = int(self.address) + self.nodesize -- Gitee From 1051e68dfc83ad2717d063e476036b9d0bffbf46 Mon Sep 17 00:00:00 2001 From: anjiahao Date: Fri, 20 Dec 2024 14:37:24 +0800 Subject: [PATCH 046/235] pynuttx/mm:use Kconfig to control sequence number to save memory VELAPLATFO-50440 Change-Id: I654a349d5a876a106d7a5b71a52f435e626a56c3 Signed-off-by: anjiahao --- tools/pynuttx/nxgdb/mm.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tools/pynuttx/nxgdb/mm.py b/tools/pynuttx/nxgdb/mm.py index 7ec814164d6..b76c78962db 100644 --- a/tools/pynuttx/nxgdb/mm.py +++ b/tools/pynuttx/nxgdb/mm.py @@ -33,7 +33,7 @@ from .utils import Value CONFIG_MM_BACKTRACE = utils.get_symbol_value("CONFIG_MM_BACKTRACE") CONFIG_MM_BACKTRACE = -1 if CONFIG_MM_BACKTRACE is None else int(CONFIG_MM_BACKTRACE) - +CONFIG_MM_BACKTRACE_SEQNO = utils.get_symbol_value("CONFIG_MM_BACKTRACE_SEQNO") PID_MM_INVALID = -100 PID_MM_MEMPOOL = -1 @@ -106,7 +106,7 @@ class MemPoolBlock: @property def seqno(self) -> int: if not self._seqno: - self._seqno = int(self.blk["seqno"]) if CONFIG_MM_BACKTRACE >= 0 else -100 + self._seqno = int(self.blk["seqno"]) if CONFIG_MM_BACKTRACE_SEQNO else -100 return self._seqno @property @@ -458,7 +458,7 @@ class MMNode(gdb.Value, p.MMFreeNode): @property def seqno(self) -> int: - return int(self["seqno"]) if CONFIG_MM_BACKTRACE >= 0 else -1 + return int(self["seqno"]) if CONFIG_MM_BACKTRACE_SEQNO else -1 @property def backtrace(self) -> List[Tuple[int, str, str]]: -- Gitee From 7c36eb2c228822836b3406042c1e254aa13c831d Mon Sep 17 00:00:00 2001 From: xuxingliang Date: Mon, 23 Dec 2024 10:09:20 +0800 Subject: [PATCH 047/235] nxgdb/net: fix diag report error VELAPLATFO-48924 Should always return a dict to show the result Change-Id: I768274eb52a04a128e584c1912825e4c66070ff7 Signed-off-by: xuxingliang --- tools/pynuttx/nxgdb/net.py | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/tools/pynuttx/nxgdb/net.py b/tools/pynuttx/nxgdb/net.py index ffb23a113d4..e4a95c1614c 100644 --- a/tools/pynuttx/nxgdb/net.py +++ b/tools/pynuttx/nxgdb/net.py @@ -281,13 +281,13 @@ class NetCheck(gdb.Command): result = max(result, ret) message.extend(msg) - return { - "title": "Netcheck Report", - "summary": "Net status check", - "result": "pass" if result else "fail", - "command": "netcheck", - "data": message, - } + return { + "title": "Netcheck Report", + "summary": "Net status check", + "result": "pass" if result else "fail", + "command": "netcheck", + "data": message, + } def check_iob(self): result = NetCheckResult.PASS -- Gitee From 823a934072bda6b6bc5628fda73743972aa4ef7b Mon Sep 17 00:00:00 2001 From: xuxingliang Date: Thu, 26 Dec 2024 17:02:04 +0800 Subject: [PATCH 048/235] nxgdb/utils: return None for value that's optimized out VELAPLATFO-50588 Change-Id: I6ea43feec3e745b83a5b5ad052ffde0a5775c9c9 Signed-off-by: xuxingliang --- tools/pynuttx/nxgdb/utils.py | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/tools/pynuttx/nxgdb/utils.py b/tools/pynuttx/nxgdb/utils.py index 8eccfc588f5..3b839b1e972 100644 --- a/tools/pynuttx/nxgdb/utils.py +++ b/tools/pynuttx/nxgdb/utils.py @@ -352,10 +352,13 @@ def parse_and_eval(expression: str, global_context: bool = False): return Value(gdb_value) -def gdb_eval_or_none(expresssion): +def gdb_eval_or_none(expression): """Evaluate an expression and return None if it fails""" try: - return parse_and_eval(expresssion) + value = parse_and_eval(expression) + if value.is_optimized_out: + return None + return value except gdb.error: return None -- Gitee From ffdaaef6b2161a205ea88b10d1d817c041f5133f Mon Sep 17 00:00:00 2001 From: xuxingliang Date: Thu, 12 Dec 2024 09:51:04 +0800 Subject: [PATCH 049/235] nxgdb/utils: fix enum parsing when no prefix available VELAPLATFO-48924 (gdb) py print('\n'.join(t.name for t in tstate)) TSTATE_TASK_INVALID TSTATE_TASK_PENDING TSTATE_TASK_READYTORUN TSTATE_TASK_RUNNING TSTATE_TASK_INACTIVE TSTATE_WAIT_SEM TSTATE_WAIT_SIG TSTATE_WAIT_MQNOTEMPTY TSTATE_WAIT_MQNOTFULL NUM_TASK_STATES Change-Id: I95d5277f428729dc6764317f0f4528ea1dc8626c Signed-off-by: xuxingliang --- tools/pynuttx/nxgdb/utils.py | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/tools/pynuttx/nxgdb/utils.py b/tools/pynuttx/nxgdb/utils.py index 3b839b1e972..114a08c05a8 100644 --- a/tools/pynuttx/nxgdb/utils.py +++ b/tools/pynuttx/nxgdb/utils.py @@ -962,7 +962,12 @@ def enum(t: Union[str, gdb.Type], name=None): names = {f.name[len(prefix) :]: f.enumval for f in t.fields()} - name = name or prefix[:-1] if prefix[-1] == "_" else prefix + if not name: + if prefix: + name = prefix[:-1] if prefix[-1] == "_" else prefix + else: + name = "Enum" + return Enum(name, names) -- Gitee From 3036341729b7869037e5f6c2031c9a720054e77c Mon Sep 17 00:00:00 2001 From: xuxingliang Date: Mon, 6 Jan 2025 13:36:13 +0800 Subject: [PATCH 050/235] pynuttx: add Dockerfile to install pynuttx required packages VELAPLATFO-51625 Change-Id: Ia11f0b6a71ccece7d4d7d81a1c6ccb5fab61d096 Signed-off-by: xuxingliang --- tools/pynuttx/Dockerfile | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) create mode 100644 tools/pynuttx/Dockerfile diff --git a/tools/pynuttx/Dockerfile b/tools/pynuttx/Dockerfile new file mode 100644 index 00000000000..cafdcfc6edd --- /dev/null +++ b/tools/pynuttx/Dockerfile @@ -0,0 +1,19 @@ +FROM alpine:latest + +RUN apk update && apk add --no-cache \ + python3 \ + py3-pip \ + gdb-multiarch \ + build-base \ + && rm -rf /var/cache/apk/* + +COPY requirements.txt . + +RUN pip3 install --break-system-packages --no-cache-dir -r requirements.txt + +# Clean up the cache and temporary files + +RUN rm -rf /var/cache/apk/* \ + && rm -rf /root/.cache + +CMD ["/bin/sh"] -- Gitee From 47d9f9443208090056d315d25d1365fa62c084f2 Mon Sep 17 00:00:00 2001 From: xuxingliang Date: Mon, 6 Jan 2025 14:59:26 +0800 Subject: [PATCH 051/235] pynuttx: update requirements to include lief VELAPLATFO-51625 And remove the hardcoded version number, since we don't have specific requirements on them. Remove the packages we don't need directly. Change-Id: I8db4e73afff8265eeda5cd2daa7e48fe2e763fa0 Signed-off-by: xuxingliang --- tools/pynuttx/requirements.txt | 22 +++++++--------------- 1 file changed, 7 insertions(+), 15 deletions(-) diff --git a/tools/pynuttx/requirements.txt b/tools/pynuttx/requirements.txt index f7c3af36452..77d779c645e 100644 --- a/tools/pynuttx/requirements.txt +++ b/tools/pynuttx/requirements.txt @@ -1,15 +1,7 @@ -construct==2.10.70 -contourpy==1.3.0 -cycler==0.12.1 -debugpy==1.8.7 -fonttools==4.54.1 -kiwisolver==1.4.7 -matplotlib==3.9.2 -numpy==2.1.2 -packaging==24.1 -pillow==11.0.0 -protobuf==4.25.3 -pyelftools==0.31 -pyparsing==3.2.0 -python-dateutil==2.9.0.post0 -six==1.16.0 +construct +debugpy +lief +matplotlib +numpy +pillow +pyelftools -- Gitee From 914641e2caa2f2c8cf7248c1477d09498b869094 Mon Sep 17 00:00:00 2001 From: buxiasen Date: Tue, 7 Jan 2025 23:12:35 +0800 Subject: [PATCH 052/235] pynuttx: fix elftools import problem, need install py apk add VELAPLATFO-51625 Change-Id: I46c66f7b5cdd2f4aab6133f685404aa38975144e Signed-off-by: buxiasen --- tools/pynuttx/Dockerfile | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/tools/pynuttx/Dockerfile b/tools/pynuttx/Dockerfile index cafdcfc6edd..62f9122c0c2 100644 --- a/tools/pynuttx/Dockerfile +++ b/tools/pynuttx/Dockerfile @@ -2,6 +2,7 @@ FROM alpine:latest RUN apk update && apk add --no-cache \ python3 \ + py3-elftools \ py3-pip \ gdb-multiarch \ build-base \ @@ -17,3 +18,6 @@ RUN rm -rf /var/cache/apk/* \ && rm -rf /root/.cache CMD ["/bin/sh"] + +# docker build -t pynuttx-alphine . +# docker image save pynuttx-alphine | xz -zc -> pynuttx-alphine.tar.xz -- Gitee From eb9403413bd42bd9db033128d27d065e1c931be3 Mon Sep 17 00:00:00 2001 From: liwenxiang1 Date: Mon, 23 Dec 2024 16:15:15 +0800 Subject: [PATCH 053/235] gdbserver.py:add x86_64 arch VELAPLATFO-50122 Change-Id: I0c46bc61f0ecaea2805acf47d96abfda9a8de9aa Signed-off-by: liwenxiang1 --- tools/gdbserver.py | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/tools/gdbserver.py b/tools/gdbserver.py index 5d5cecee2a3..6b82767530d 100755 --- a/tools/gdbserver.py +++ b/tools/gdbserver.py @@ -55,6 +55,31 @@ DEFAULT_GDB_INIT_CMD = "-ex 'bt full' -ex 'info reg' -ex 'display /40i $pc-40'" logger = logging.getLogger() reg_table = { + "x86_64": { + "RAX": 0, + "RBX": 1, + "RCX": 2, + "RDX": 3, + "RSI": 4, + "RDI": 5, + "RBP": 6, + "FSP": 7, + "R8": 8, + "R9": 9, + "R10": 10, + "R11": 11, + "R12": 12, + "R13": 13, + "R14": 14, + "R15": 15, + "RIP": 16, + "RFLAGS": 17, + "CS": 18, + "SS": 19, + "DS": 20, + "ES": 21, + "FS": 22, + }, "arm": { "R0": 0, "R1": 1, -- Gitee From 60cb349417c9e248d82efcace364d81b1ecee3e9 Mon Sep 17 00:00:00 2001 From: xuxingliang Date: Thu, 2 Jan 2025 01:49:29 +0800 Subject: [PATCH 054/235] nxstub: refactor gdbserver for better maintainability VELAPLATFO-43422 Change-Id: I8628cb85e54b46789a730e2733cc33f1bc1d02bb Signed-off-by: xuxingliang --- tools/gdbserver.py | 1239 +---------------------------- tools/pynuttx/.gitignore | 1 + tools/pynuttx/nxstub/__init__.py | 251 ++++++ tools/pynuttx/nxstub/__main__.py | 24 + tools/pynuttx/nxstub/gdbstub.py | 269 +++++++ tools/pynuttx/nxstub/registers.py | 356 +++++++++ tools/pynuttx/nxstub/target.py | 228 ++++++ tools/pynuttx/nxstub/utils.py | 214 +++++ tools/pynuttx/setup.py | 11 +- 9 files changed, 1355 insertions(+), 1238 deletions(-) create mode 100644 tools/pynuttx/nxstub/__init__.py create mode 100644 tools/pynuttx/nxstub/__main__.py create mode 100644 tools/pynuttx/nxstub/gdbstub.py create mode 100644 tools/pynuttx/nxstub/registers.py create mode 100644 tools/pynuttx/nxstub/target.py create mode 100644 tools/pynuttx/nxstub/utils.py diff --git a/tools/gdbserver.py b/tools/gdbserver.py index 6b82767530d..b57221a8d39 100755 --- a/tools/gdbserver.py +++ b/tools/gdbserver.py @@ -19,1243 +19,12 @@ # under the License. # -import argparse -import binascii -import logging -import multiprocessing import os -import re -import shutil -import socket -import struct -import subprocess import sys -import traceback -try: - import lief -except ImportError: - print("Please install lief package: pip3 install lief") - sys.exit(1) +here = os.path.dirname(os.path.realpath(__file__)) +sys.path.insert(0, (os.path.join(here, "pynuttx"))) -# ELF section flags -SHF_WRITE = 0x1 -SHF_ALLOC = 0x2 -SHF_EXEC = 0x4 -SHF_WRITE_ALLOC = SHF_WRITE | SHF_ALLOC -SHF_ALLOC_EXEC = SHF_ALLOC | SHF_EXEC +import nxstub # noqa: E402 -GDB_SIGNAL_DEFAULT = 7 - -UINT16_MAX = 65535 - - -DEFAULT_GDB_INIT_CMD = "-ex 'bt full' -ex 'info reg' -ex 'display /40i $pc-40'" - -logger = logging.getLogger() - -reg_table = { - "x86_64": { - "RAX": 0, - "RBX": 1, - "RCX": 2, - "RDX": 3, - "RSI": 4, - "RDI": 5, - "RBP": 6, - "FSP": 7, - "R8": 8, - "R9": 9, - "R10": 10, - "R11": 11, - "R12": 12, - "R13": 13, - "R14": 14, - "R15": 15, - "RIP": 16, - "RFLAGS": 17, - "CS": 18, - "SS": 19, - "DS": 20, - "ES": 21, - "FS": 22, - }, - "arm": { - "R0": 0, - "R1": 1, - "R2": 2, - "R3": 3, - "R4": 4, - "R5": 5, - "R6": 6, - "FP": 7, - "R8": 8, - "SB": 9, - "SL": 10, - "R11": 11, - "IP": 12, - "SP": 13, - "LR": 14, - "PC": 15, - "xPSR": 16, - }, - "arm-a": { - "R0": 0, - "R1": 1, - "R2": 2, - "R3": 3, - "R4": 4, - "R5": 5, - "R6": 6, - "FP": 7, - "R8": 8, - "SB": 9, - "SL": 10, - "R11": 11, - "IP": 12, - "SP": 13, - "LR": 14, - "PC": 15, - "CPSR": 41, - }, - "arm-t": { - "R0": 0, - "R1": 1, - "R2": 2, - "R3": 3, - "R4": 4, - "R5": 5, - "R6": 6, - "FP": 7, - "R8": 8, - "SB": 9, - "SL": 10, - "R11": 11, - "IP": 12, - "SP": 13, - "LR": 14, - "PC": 15, - "CPSR": 41, - }, - "arm64": { - "X0": 0, - "X1": 1, - "X2": 2, - "X3": 3, - "X4": 4, - "X5": 5, - "X6": 6, - "X7": 7, - "X8": 8, - "X9": 9, - "X10": 10, - "X11": 11, - "X12": 12, - "X13": 13, - "X14": 14, - "X15": 15, - "X16": 16, - "X17": 17, - "X18": 18, - "X19": 19, - "X20": 20, - "X21": 21, - "X22": 22, - "X23": 23, - "X24": 24, - "X25": 25, - "X26": 26, - "X27": 27, - "X28": 28, - "X29": 29, - "X30": 30, - "SP_ELX": 31, - "ELR": 32, - }, - "riscv": { - "ZERO": 0, - "RA": 1, - "SP": 2, - "GP": 3, - "TP": 4, - "T0": 5, - "T1": 6, - "T2": 7, - "FP": 8, - "S1": 9, - "A0": 10, - "A1": 11, - "A2": 12, - "A3": 13, - "A4": 14, - "A5": 15, - "A6": 16, - "A7": 17, - "S2": 18, - "S3": 19, - "S4": 20, - "S5": 21, - "S6": 22, - "S7": 23, - "S8": 24, - "S9": 25, - "S10": 26, - "S11": 27, - "T3": 28, - "T4": 29, - "T5": 30, - "T6": 31, - "EPC": 32, - }, - # use xtensa-esp32s3-elf-gdb register table - "esp32s3": { - "PC": 0, - "PS": 73, - "A0": 1, - "A1": 2, - "A2": 3, - "A3": 4, - "A4": 5, - "A5": 6, - "A6": 7, - "A7": 8, - "A8": 9, - "A9": 10, - "A10": 11, - "A11": 12, - "A12": 13, - "A13": 14, - "A14": 15, - "A15": 16, - "WINDOWBASE": 69, - "WINDOWSTART": 70, - "CAUSE": 190, - "VADDR": 196, - "LBEG": 65, - "LEND": 66, - "LCNT": 67, - "SAR": 68, - "SCOM": 76, - }, - # use xt-gdb register table - "xtensa": { - "PC": 32, - "PS": 742, - "A0": 256, - "A1": 257, - "A2": 258, - "A3": 259, - "A4": 260, - "A5": 261, - "A6": 262, - "A7": 263, - "A8": 264, - "A9": 265, - "A10": 266, - "A11": 267, - "A12": 268, - "A13": 269, - "A14": 270, - "A15": 271, - "WINDOWBASE": 584, - "WINDOWSTART": 585, - "CAUSE": 744, - "VADDR": 750, - "LBEG": 512, - "LEND": 513, - "LCNT": 514, - "SAR": 515, - "SCOM": 524, - }, -} - -# make sure the a0-a15 can be remapped to the correct register -reg_fix_value = { - "esp32s3": { - "WINDOWBASE": (0, 69), - "WINDOWSTART": (1, 70), - "PS": (0x40000, 73), - }, - "xtensa": { - "WINDOWBASE": (0, 584), - "WINDOWSTART": (1, 585), - "PS": (0x40000, 742), - }, -} - - -def str_get_after(s, sub): - index = s.find(sub) - if index == -1: - return None - return s[index + len(sub) :] - - -def pack_memory(start, end, data): - return {"start": start, "end": end, "data": data} - - -class DumpELFFile: - """ - Class to parse ELF file for memory content in various sections. - There are read-only sections (e.g. text and rodata) where - the memory content does not need to be dumped via coredump - and can be retrieved from the ELF file. - """ - - def __init__(self, elffile: str): - self.elffile = elffile - self.__memories = [] - self.__arch = None - self.__xlen = None - - def parse(self, load_symbol: bool): - self.__memories = [] - elf = lief.parse(self.elffile) - self.__arch = elf.header.machine_type.name.lower().replace("-", "") - if elf.header.identity_class == lief.ELF.Header.CLASS.ELF32: - self.__xlen = 32 - else: - self.__xlen = 64 - - for section in elf.sections: - size = section.size - flags = section.flags - start = section.virtual_address - end = start + size - 1 - store = False - desc = "?" - if section.type == lief.ELF.Section.TYPE.PROGBITS: - if (flags & SHF_ALLOC_EXEC) == SHF_ALLOC_EXEC: - # Text section - store = True - desc = "text" - elif (flags & SHF_WRITE_ALLOC) == SHF_WRITE_ALLOC: - # Data or Rodata section, rodata store in ram in some case - store = True - desc = "data or rodata" - elif (flags & SHF_ALLOC) == SHF_ALLOC: - # Read only data section - store = True - desc = "read-only data" - if store: - memory = pack_memory(start, end, bytes(section.content)) - logger.debug( - f"ELF Section: {hex(memory['start'])} to {hex(memory['end'])} of size {len(memory['data'])} ({desc})" - ) - self.__memories.append(memory) - self.load_symbol = load_symbol - if load_symbol: - self.symbol = {} - for symbol in elf.symbols: - if symbol.name in ( - "g_tcbinfo", - "g_pidhash", - "g_npidhash", - "g_last_regs", - "g_running_tasks", - ): - self.symbol[symbol.name] = {} - self.symbol[symbol.name]["st_size"] = symbol.size - self.symbol[symbol.name]["st_value"] = symbol.value - logger.debug( - f"name:{symbol.name} size:{symbol.size} value:{hex(symbol.value)}" - ) - return True - - def _parse_addr2line(self, addr2line: str, args: list, addr: str) -> str: - args_string = " ".join(args) - cmd = "{} {} {}".format(addr2line, args_string, addr) - return subprocess.check_output(cmd, universal_newlines=True, shell=True) - - def parse_addr2line(self, arch: str, addr2line: str, addr_list: list): - if addr2line is None: - return - - is_audio = False - if arch == "xtensa": - is_audio = True - - for i in addr_list: - addr = int(i, 16) - if addr == 0: - continue - - if is_audio: - addr &= 0x7FFFFFFF - - res = self._parse_addr2line( - addr2line, ["-Cfe", self.elffile, "-a"], hex(addr) - ) - matches = re.findall(r"\?\?:", res) - if matches: - continue - print(res) - exit(0) - - def get_memories(self): - return self.__memories - - def arch(self): - return self.__arch - - def xlen(self): - return self.__xlen - - -class DumpLogFile: - def __init__(self, logfile): - self.logfile = logfile - self.registers = [] - self.stack_data = [] - self.__memories = list() - self.reg_table = dict() - self.reg_len = 32 - - def _init_register(self): - self.registers = [b"x"] * (max(self.reg_table.values()) + 1) - - def _parse_register(self, line): - line = str_get_after(line, "up_dump_register:") - if line is None: - return False - - line = line.strip() - # find register value - find_res = re.findall(r"(?P\w+):\s*(?P[0-9a-fxA-FX]+)", line) - - for reg_name, reg_val in find_res: - reg_name = reg_name.upper() - if reg_name in self.reg_table: - reg_index = self.reg_table[reg_name] - self.registers[reg_index] = int(reg_val, 16) - self.reg_len = max(self.reg_len, len(reg_val) * 4) - - return True - - def _parse_fix_register(self, arch): - if arch in reg_fix_value: - for reg_name, reg_vals in reg_fix_value[arch].items(): - reg_index = self.reg_table[reg_name] - self.registers[reg_index] = reg_vals[0] - - def _parse_stack(self, line, start, data): - line = str_get_after(line, "stack_dump:") - if line is None: - return None - - line = line.strip() - - # find stack-dump - match_res = re.match(r"(?P0x\w+): (?P( ?\w+)+)", line) - if match_res is None: - return None - - self.stack_data.extend(match_res.string.split(" ")[1:]) - - addr_start = int(match_res.groupdict()["ADDR_START"], 16) - if start + len(data) != addr_start: - # stack is not contiguous - if len(data) == 0: - start = addr_start - else: - self.__memories.append(pack_memory(start, start + len(data), data)) - data = b"" - start = addr_start - - reg_fmt = " unknown value - # Send in "xxxxxxxx" - pkt += b"x" * self.reg_digits - - self.put_gdb_packet(pkt) - - if not self.threadinfo: - put_register_packet(self.registers) - else: - for thread in self.threadinfo: - if thread["tcb"]["pid"] == self.current_thread: - if thread["tcb"]["tcbptr"] in self.running_tasks.keys(): - put_register_packet(self.running_tasks[thread["tcb"]["tcbptr"]]) - else: - put_register_packet(thread["gdb_regs"]) - break - - def handle_register_single_read_packet(self, pkt): - logger.debug(f"pkt: {pkt}") - - def put_one_register_packet(regs): - - reg_fmt = self.reg_fmt - reg = int(pkt[1:].decode("utf8"), 16) - regval = None - - if self.regfix: - for reg_name, reg_vals in reg_fix_value[self.arch].items(): - if reg == reg_vals[1]: - logger.debug(f"{reg_name} fix to {reg_vals[0]}") - regval = reg_vals[0] - - if regval is None: - # tcbinfo index to gdb index - reg_gdb_index = list(reg_table[self.arch].values()) - if reg in reg_gdb_index: - reg = reg_gdb_index.index(reg) - regval = regs[reg] - - elif reg < len(regs) and regs[reg] != b"x": - regval = regs[reg] - - if regval is not None: - bval = struct.pack(reg_fmt, regval) - self.put_gdb_packet(binascii.hexlify(bval)) - else: - self.put_gdb_packet(b"x" * self.reg_digits) - - if not self.threadinfo: - put_one_register_packet(self.registers) - else: - for thread in self.threadinfo: - if thread["tcb"]["pid"] == self.current_thread: - if thread["tcb"]["tcbptr"] in self.running_tasks.keys(): - put_one_register_packet( - self.running_tasks[thread["tcb"]["tcbptr"]] - ) - else: - put_one_register_packet(thread["gdb_regs"]) - break - - def handle_register_group_write_packet(self): - # the 'G' packet for writing to a group of registers - # - # We don't support writing so return error - self.put_gdb_packet(b"E01") - - def handle_register_single_write_packet(self, pkt): - # the 'P' packet for writing to registers - - index, value = pkt[1:].split(b"=") - reg_val = 0 - for i in range(0, len(value), 2): - data = value[i : i + 2] - reg_val = reg_val + (int(data.decode("utf8"), 16) << (i * 4)) - - reg = int(index.decode("utf8"), 16) - if reg < len(self.registers): - self.registers[reg] = reg_val - - self.put_gdb_packet(b"OK") - - def get_mem_region(self, addr, mem_regions=None): - mem_regions = mem_regions or self.mem_regions - for mem in mem_regions: - if mem["start"] <= addr < mem["end"]: - return mem - - return None - - def handle_memory_read_packet(self, pkt): - # the 'm' packet for reading memory: m, - - # extract address and length from packet - # and convert them into usable integer values - addr, length = pkt[1:].split(b",") - s_addr = int(addr, 16) - length = int(length, 16) - - remaining = length - addr = s_addr - barray = b"" - r = self.get_mem_region(addr) - while remaining > 0: - if r is None: - barray = None - break - - offset = addr - r["start"] - barray += r["data"][offset : offset + 1] - - addr += 1 - remaining -= 1 - - if barray is not None: - pkt = binascii.hexlify(barray) - self.put_gdb_packet(pkt) - else: - self.put_gdb_packet(b"E01") - - def handle_memory_write_packet(self, pkt): - # the 'M' packet for writing to memory - # - # We don't support writing so return error - self.put_gdb_packet(b"E02") - - def handle_is_thread_active(self, pkt): - self.current_thread = int(pkt[1:]) - 1 - self.put_gdb_packet(b"OK") - - def handle_thread_context(self, pkt): - if b"g" == pkt[1:2]: - self.current_thread = int(pkt[2:]) - 1 - elif b"c" == pkt[1:2]: - self.current_thread = int(pkt[3:]) - 1 - - if self.current_thread == -1: - self.current_thread = 0 - self.put_gdb_packet(b"OK") - - def parse_thread(self): - def unpack_data(addr, fmt, from_elf=False): - logger.debug( - f"Unpack data from {hex(addr)} with fmt {fmt} from elf {from_elf}" - ) - if from_elf: - r = self.get_mem_region(addr, self.elffile.get_memories()) - else: - r = self.get_mem_region(addr) - offset = addr - r["start"] - data = r["data"] - return struct.unpack_from(fmt, data, offset) - - TCBINFO_FMT = "<8HQ" - - # uint16_t pid_off; /* Offset of tcb.pid */ - # uint16_t state_off; /* Offset of tcb.task_state */ - # uint16_t pri_off; /* Offset of tcb.sched_priority */ - # uint16_t name_off; /* Offset of tcb.name */ - # uint16_t stack_off; /* Offset of tcb.stack_alloc_ptr */ - # uint16_t stack_size_off; /* Offset of tcb.adj_stack_size */ - # uint16_t regs_off; /* Offset of tcb.regs */ - # uint16_t regs_num; /* Num of general regs */ - # union - # { - # uint8_t u[8]; - # FAR const uint16_t *p; - # } - - unpacked_data = unpack_data( - self.elffile.symbol["g_tcbinfo"]["st_value"], - TCBINFO_FMT, - True, - ) - tcbinfo = { - "pid_off": int(unpacked_data[0]), - "state_off": int(unpacked_data[1]), - "pri_off": int(unpacked_data[2]), - "name_off": int(unpacked_data[3]), - "stack_off": int(unpacked_data[4]), - "stack_size_off": int(unpacked_data[5]), - "regs_off": int(unpacked_data[6]), - "regs_num": int(unpacked_data[7]), - "reg_off": int(unpacked_data[8]), - } - - unpacked_data = unpack_data( - self.elffile.symbol["g_npidhash"]["st_value"], - "[0-9a-fxA-FX]+): (?P( ?\w+)+)", line + ) + if result is None: + return None + + results = result.groupdict() + + addr = int(results["ADDR"], 16) + data = b"" + for val in results["VALS"].split(): + # For little endian, the hex bytes should be reversed + data += bytes.fromhex(val)[::-1] + return RawMemory(addr, data) + + registerdump = [] + parsing_regs = False + lines = [] + with open(logfile, "r") as f: + for line in f: + line = line.strip() + if is_register_dump(line): + if not parsing_regs: + parsing_regs = True + if lines: # Started + registers.append(tmpregisters) # noqa + memories.append(tempmemories) # noqa + registerdump.append(lines) + lines = [] + tempmemories = [] + tmpregisters = Registers(elf, arch) + + lines.append(line) + parse_register(tmpregisters, line) + elif memory := parse_stack(line): + parsing_regs = False + tempmemories.append(memory) + + if lines: + registers.append(tmpregisters) + memories.append(tempmemories) + registerdump.append(lines) + + if len(memories) > 1: + for i, line in enumerate(registerdump): + print(f"[{i}]: {' '.join(line[:2])}") + + choice = input("Multiple dump found, please choose one:\n").strip() or 0 + else: + choice = 0 + + return registers[int(choice)], memories[int(choice)] + + +def gdbstub_start(args): + memories = [] + registers = None + + for rawfile in args.rawfile or []: + filename, address = rawfile.split(":") + address = int(address, 16) + with open(filename, "rb") as f: + memories.append(RawMemory(address, f.read())) + print(f"Add memory dump: {memories[-1]}") + + elf = utils.parse_elf(args.elffile) + registers, mem = parse_log(elf, args.arch, args.log) + memories.extend(mem) + + core = utils.parse_elf(args.core) if args.core else None + target = Target(elf, args.arch, registers, memories, core) + + stub = GDBStub(target=target, port=args.port) + + print(f"Start GDB server on port {args.port}...") + stub.run() + print("GDB server exited.") + + +def gdb_start(args): + def gdb_run(cmd): + try: + subprocess.run(cmd, shell=True) + except KeyboardInterrupt: + pass + + gdb_init_cmd = args.init_cmd or DEFAULT_GDB_INIT_CMD + gdb_exec = args.gdb or "gdb-multiarch" + gdb_cmd = ( + f"{gdb_exec} {args.elffile} -ex 'target remote localhost:{args.port}' " + f"{gdb_init_cmd}" + ) + print(f"Start GDB session: {gdb_cmd}") + return multiprocessing.Process(target=gdb_run, args=(gdb_cmd,)).start() + + +def parse_args(args=None): + parser = argparse.ArgumentParser( + prog="nxstub", + description=f"nxstub v{__version__} - NuttX GDB server based on crash log, core dump or memory dump.", + ) + parser.add_argument( + "-a", + "--arch", + type=str, + required=True, + choices=g_reg_table.keys(), + help="The architecture of the target.", + ) + parser.add_argument( + "-e", + "--elffile", + type=str, + required=True, + help="The elf file.", + ) + parser.add_argument( + "-p", + "--port", + type=int, + default=1234, + help="The GDB server port.", + ) + parser.add_argument( + "-r", + "--rawfile", + type=str, + nargs="*", + help="The memory dump file, in format of 'memdump1.bin:address1 memdump2.bin:address2'.", + ) + parser.add_argument( + "-c", + "--core", + type=str, + help="The core dump file.", + ) + parser.add_argument( + "-l", + "--log", + type=str, + help="The crash dump log file.", + ) + parser.add_argument( + "-d", + "--debug", + action="store_true", + help="Show debug messages.", + ) + parser.add_argument( + "-g", + "--gdb", + help="Optional path to GDB executable, once specified, will automatically start GDB session.", + type=str, + ) + parser.add_argument( + "-i", + "--init-cmd", + type=str, + help=f'Optional custom GDB init command when GDB launches, default: "{DEFAULT_GDB_INIT_CMD}".', + ) + + return parser.parse_args(args) + + +def main(args=None): + args = parse_args(args) + + gdb = None + if args.debug: + logging.basicConfig() + logger = logging.getLogger(__name__) + logger.setLevel(logging.DEBUG if args.debug else logging.INFO) + + if args.gdb: + gdb = gdb_start(args) + # Ignore the Ctrl+C signal + signal.signal(signal.SIGINT, signal.SIG_IGN) + + try: + gdbstub_start(args) + except Exception as e: + print(f"GDBStub error: {e}:\n {traceback.format_exc()}") + + if gdb: + gdb.kill() + gdb.join() diff --git a/tools/pynuttx/nxstub/__main__.py b/tools/pynuttx/nxstub/__main__.py new file mode 100644 index 00000000000..8811d639863 --- /dev/null +++ b/tools/pynuttx/nxstub/__main__.py @@ -0,0 +1,24 @@ +############################################################################ +# tools/pynuttx/nxstub/__main__.py +# +# Licensed to the Apache Software Foundation (ASF) under one or more +# contributor license agreements. See the NOTICE file distributed with +# this work for additional information regarding copyright ownership. The +# ASF licenses this file to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance with the +# License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# +############################################################################ + +from . import main + +if __name__ == "__main__": + main() diff --git a/tools/pynuttx/nxstub/gdbstub.py b/tools/pynuttx/nxstub/gdbstub.py new file mode 100644 index 00000000000..7e9d42d26d0 --- /dev/null +++ b/tools/pynuttx/nxstub/gdbstub.py @@ -0,0 +1,269 @@ +############################################################################ +# tools/pynuttx/nxstub/gdbstub.py +# +# SPDX-License-Identifier: Apache-2.0 +# +# Licensed to the Apache Software Foundation (ASF) under one or more +# contributor license agreements. See the NOTICE file distributed with +# this work for additional information regarding copyright ownership. The +# ASF licenses this file to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance with the +# License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# +############################################################################ + +import logging +import socket +import traceback +from binascii import hexlify, unhexlify +from typing import Union + +from .target import Target + + +class GDBStub: + def __init__( + self, + target: Target, + port=1234, + ): + self.threads = target.update_threads() + self.registers = target.switch_thread() + self.target = target + self.exiting = False + self.socket = None + self.port = port + self.logger = logging.getLogger(__name__) + + def run(self): + self.socket = self.wait_connect() + if self.socket is None: + return + + while not self.exiting: + try: + packet = self.get_packet() + if packet is None: + self.logger.info("Connection closed") + return + + self.process_packet(packet) + + except Exception as e: + self.logger.error(f"Error in stub thread: {e} {traceback.format_exc()}") + self.logger.info("Stub thread exited") + + def wait_connect(self) -> socket.socket: + listener = socket.socket(socket.AF_INET, socket.SOCK_STREAM) + listener.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1) + listener.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) + + port = self.port + try: + listener.bind(("localhost", port)) + self.logger.info(f"Listening on localhost:{port}") + listener.listen(1) + except socket.error as e: + self.logger.error( + f"Cannot listen on localhost:{port}: error {e[0]} - {e[1]}" + ) + return None + + client, addr = listener.accept() + self.logger.info(f"Client connected from {addr[0]}:{addr[1]}") + listener.close() + return client + + def get_packet(self) -> Union[bytes, None]: + buffer = bytearray() + started = False + escaping = False + checksum = 0 + while True: + c = self.socket.recv(1) + if not started: + if c == b"\x03": + return b"\x03" + if c == b"$": + started = True + continue + + if escaping: + c ^= 0x20 + escaping = False + elif c == b"}": + escaping = True + checksum += ord(c) + continue + + if c == b"#": + expected = self.socket.recv(2) + expected = int(expected.decode("ascii"), 16) + if expected != checksum & 0xFF: + self.logger.error( + f"checksum error: {expected:#x} != {checksum & 0xFF:#x}" + ) + self.socket.send(b"-") # No ack + checksum = 0 + started = False + buffer = bytearray() + continue + else: + self.socket.send(b"+") + break + else: + checksum += ord(c) + buffer.append(ord(c)) + + self.logger.debug(f"Received packet: {buffer}") + return bytes(buffer) + + def send_raw_packet(self, data: bytes, nowait=False) -> bool: + checksum = sum(data) & 0xFF + self.socket.send(b"$") + self.socket.send(data) + self.socket.send(b"#") + self.socket.send(b"%02x" % checksum) + self.logger.debug(f"Sent packet: {data}") + if nowait: + return True + ack = self.socket.recv(1) + return ack == b"+" + + def send_packet(self, packet: Union[bytes, str], nowait=False) -> None: + if isinstance(packet, str): + packet = packet.encode("ascii") + + output = list() + for c in packet: + if c in b"$#*}": + output.append(ord("}")) + c ^= 0x20 + output.append(c) + return self.send_raw_packet(bytes(output), nowait) + + def send_unsupported(self): + self.send_packet("") + + def process_packet(self, packet: bytes): + attribute = "handle_" + chr(packet[0]) + handler = { + "handle_?": self.handle_questionmark, + "handle_\x03": self.handle_etx, + }.get(attribute) + + if not handler and not hasattr(self, attribute): + self.logger.error(f"Unsupported packet: {packet}") + self.send_unsupported() + return + + handler = handler or getattr(self, attribute) + + try: + handler(packet) + except Exception as e: + self.logger.error(f"Error packet{packet}: {e}\n {traceback.format_exc()}") + self.send_packet("EF1") + + def handle_q(self, packet: bytes): + packet = packet.decode("ascii") + if packet.startswith("qSupported"): + self.send_packet("PacketSize=FFFF") + elif packet.startswith("qC"): + pid = next((t.pid for t in self.threads if t.state == "Running"), 0) + self.logger.debug(f"Current thread: {pid}") + self.send_packet(f"QC{pid:x}") + elif packet.startswith("qfThreadInfo"): + reply = "".join(f"{thread.pid:x}," for thread in self.threads) + reply = "m" + reply[:-1] if reply else "l" + self.send_packet(reply) + elif packet.startswith("qsThreadInfo"): + self.send_packet("l") + elif packet.startswith("qThreadExtraInfo"): + pid = int(packet.split(",")[1], 16) + info = next((t for t in self.threads if t.pid == pid), None) + info = f"{info.name},{info.state}" if info else f"Invalid PID {pid}" + self.send_packet(hexlify(info.encode("ascii"))) + else: + self.send_unsupported() + + def handle_v(self, packet: bytes): + if packet.startswith(b"vMustReplyEmpty"): + self.send_packet("") + else: + self.send_unsupported() + + def handle_questionmark(self, packet: bytes): + self.send_packet("S05") + + def handle_g(self, packet: bytes): + reply = b"" + offset = 0 + for reg in self.registers: + if reg.offset and reg.offset != offset: + reply += b"xx" * (reg.offset - offset) + + if not reg.has_value: + reply += b"xx" * reg.size + else: + reply += hexlify(bytes(reg)) + + offset += reg.offset + reg.size + self.send_packet(reply) + + def handle_p(self, packet: bytes): + packet = packet.decode("ascii") + regnum = int(packet[1:], 16) + reg = self.registers.get(regnum=regnum) + self.send_packet(hexlify(bytes(reg)) if reg else b"xx" * 4) + + def handle_P(self, packet: bytes): + packet = packet.decode("ascii") + regnum, value = packet[1:].split("=") + regnum = int(regnum, 16) + value = unhexlify(value) + self.registers.set(regnum=regnum, value=value) + self.send_packet("OK") + + def handle_m(self, packet: bytes): + packet = packet.decode("ascii") + addr, length = packet[1:].split(",") + reply = self.target.memory_read(int(addr, 16), int(length, 16)) + reply = hexlify(reply) + self.send_packet(reply) + + def handle_M(self, packet: bytes): + packet = packet.decode("ascii") + addr, length_and_data = packet[1:].split(",") + length, data = length_and_data.split(":") + ok = self.target.memory_write(int(addr, 16), unhexlify(data), int(length, 16)) + self.send_packet("OK" if ok else "") + + def handle_etx(self, packet: bytes): + # FIXME no reply needed + self.send_packet("S00") + self.logger.info("Ctrl-C received") + + def handle_k(self, packet: bytes): + self.exiting = True + self.logger.info("Kill request received") + + def handle_T(self, packet): + self.send_packet("OK") + + def handle_H(self, packet): + pid = int(packet[2:], 16) + registers = self.target.switch_thread(pid) + if not registers: + self.send_packet("E01") + return + self.registers = registers + self.send_packet("OK") diff --git a/tools/pynuttx/nxstub/registers.py b/tools/pynuttx/nxstub/registers.py new file mode 100644 index 00000000000..61b12e41277 --- /dev/null +++ b/tools/pynuttx/nxstub/registers.py @@ -0,0 +1,356 @@ +############################################################################ +# tools/pynuttx/nxstub/registers.py +# +# SPDX-License-Identifier: Apache-2.0 +# +# Licensed to the Apache Software Foundation (ASF) under one or more +# contributor license agreements. See the NOTICE file distributed with +# this work for additional information regarding copyright ownership. The +# ASF licenses this file to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance with the +# License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# +############################################################################ + +import logging +from typing import Union + +from . import utils + +UINT16_MAX = 0xFFFF + +# GDB default register information for different architectures +# +# Format: ("reg-name", regnum, g/G offset, fixed-value(optional)) +# +# To get the default register offset in g/G packet, using GDB command: +# (gdb) set architecture (e.g. set architecture arm), leave empty to see all supported architectures +# (gdb) maint print remote-registers + +g_reg_table = { + "arm": { + "architecture": "arm", + "feature": "org.gnu.gdb.arm.m-profile", + "registers": [ + ("r0", 0, 0), + ("r1", 1, 0), + ("r2", 2, 0), + ("r3", 3, 0), + ("r4", 4, 0), + ("r5", 5, 0), + ("r6", 6, 0), + ("fp", 7, 0), + ("r8", 8, 0), + ("sb", 9, 0), + ("sl", 10, 0), + ("r11", 11, 0), + ("ip", 12, 0), + ("sp", 13, 0), + ("lr", 14, 0), + ("pc", 15, 0), + ("xpsr", 16, 0), + ], + }, + "arm-a": { + "architecture": "arm", + "feature": "org.gnu.gdb.arm", + "registers": [ + ("r0", 0, 0), + ("r1", 1, 0), + ("r2", 2, 0), + ("r3", 3, 0), + ("r4", 4, 0), + ("r5", 5, 0), + ("r6", 6, 0), + ("fp", 7, 0), + ("r8", 8, 0), + ("sb", 9, 0), + ("sl", 10, 0), + ("r11", 11, 0), + ("ip", 12, 0), + ("sp", 13, 0), + ("lr", 14, 0), + ("pc", 15, 0), + ("cpsr", 25, 164), + ], + }, + "arm64": { + "architecture": "aarch64", + "feature": "org.gnu.gdb.aarch64", + "registers": [ + ("x0", 0, 0), + ("x1", 1, 0), + ("x2", 2, 0), + ("x3", 3, 0), + ("x4", 4, 0), + ("x5", 5, 0), + ("x6", 6, 0), + ("x7", 7, 0), + ("x8", 8, 0), + ("x9", 9, 0), + ("x10", 10, 0), + ("x11", 11, 0), + ("x12", 12, 0), + ("x13", 13, 0), + ("x14", 14, 0), + ("x15", 15, 0), + ("x16", 16, 0), + ("x17", 17, 0), + ("x18", 18, 0), + ("x19", 19, 0), + ("x20", 20, 0), + ("x21", 21, 0), + ("x22", 22, 0), + ("x23", 23, 0), + ("x24", 24, 0), + ("x25", 25, 0), + ("x26", 26, 0), + ("x27", 27, 0), + ("x28", 28, 0), + ("x29", 29, 0), + ("x30", 30, 0), + ("sp_elx", 31, 0), # SP + ("elr", 32, 0), # PC + ], + }, + "riscv": { + "architecture": "riscv:rv32", + "feature": "org.gnu.gdb.riscv:rv32", + "registers": [ + ("zero", 0, 0), + ("ra", 1, 0), + ("sp", 2, 0), + ("gp", 3, 0), + ("tp", 4, 0), + ("t0", 5, 0), + ("t1", 6, 0), + ("t2", 7, 0), + ("fp", 8, 0), + ("s1", 9, 0), + ("a0", 10, 0), + ("a1", 11, 0), + ("a2", 12, 0), + ("a3", 13, 0), + ("a4", 14, 0), + ("a5", 15, 0), + ("a6", 16, 0), + ("a7", 17, 0), + ("s2", 18, 0), + ("s3", 19, 0), + ("s4", 20, 0), + ("s5", 21, 0), + ("s6", 22, 0), + ("s7", 23, 0), + ("s8", 24, 0), + ("s9", 25, 0), + ("s10", 26, 0), + ("s11", 27, 0), + ("t3", 28, 0), + ("t4", 29, 0), + ("t5", 30, 0), + ("t6", 31, 0), + ("epc", 33, 0), + ], + }, + "x86-64": { + "architecture": "i386:x86-64", + "feature": "org.gnu.gdb.i386:x86-64", + "registers": [ + ("rax", 0, 0), + ("rbx", 1, 0), + ("rcx", 2, 0), + ("rdx", 3, 0), + ("rsi", 4, 0), + ("rdi", 5, 0), + ("rbp", 6, 0), + ("fsp", 7, 0), + ("r8", 8, 0), + ("r9", 9, 0), + ("r10", 10, 0), + ("r11", 11, 0), + ("r12", 12, 0), + ("r13", 13, 0), + ("r14", 14, 0), + ("r15", 15, 0), + ("rip", 16, 0), + ("rflags", 17, 0), + ("cs", 18, 0), + ("ss", 19, 0), + ("ds", 20, 0), + ("es", 21, 0), + ("fs", 22, 0), + ], + }, + "xtensa": { + "architecture": "xtensa", # Use xtensa-esp32s3-elf-gdb + "feature": "", + "registers": [ + ("pc", 0, 0), + ("ps", 73, 292, 0x40000), # g_reg_offs placed it in the second position + ("a0", 1, 0), + ("a1", 2, 0), + ("a2", 3, 0), + ("a3", 4, 0), + ("a4", 5, 0), + ("a5", 6, 0), + ("a6", 7, 0), + ("a7", 8, 0), + ("a8", 9, 0), + ("a9", 10, 0), + ("a10", 11, 0), + ("a11", 12, 0), + ("a12", 13, 0), + ("a13", 14, 0), + ("a14", 15, 0), + ("a15", 16, 0), + ("windowbase", 69, 276, 0), + ("windowstart", 70, 280, 1), + ], + }, +} + + +class Register: + def __init__( + self, name, regnum, size: int, offset=0, tcb_reg_off=0, value=0, fixedvalue=None + ): + self.name = name + self.regnum = regnum + self.size = size # size in bytes + self.offset = offset + self.tcb_reg_off = tcb_reg_off + self._value = value + self.fixedvalue = fixedvalue + self.logger = logging.getLogger(__name__) + + def __str__(self): + return f"{self.name}({self.regnum}, size:{self.size}, offset:{self.offset},{self.tcb_reg_off} value:{self.value:#x})" + + def __repr__(self): + return self.__str__() + + def __bytes__(self): + return self.value.to_bytes(self.size, "little", signed=self._value < 0) + + @property + def has_value(self): + return self._value is not None or self.fixedvalue is not None + + @property + def value(self): + return self._value if self.fixedvalue is None else self.fixedvalue + + @value.setter + def value(self, value): + """Set register value from bytes or value""" + if self.name == "": + return + + if isinstance(value, bytes) or isinstance(value, bytearray): + if len(value) != self.size: + raise ValueError( + f"Invalid value, expected {self.size} bytes, got {len(value)} bytes" + ) + self._value = int.from_bytes(bytes(value), "little") + elif isinstance(value, int): + self._value = value + else: + raise ValueError(f"Invalid value type: {type(value)}") + self.logger.debug(f"Set {self.name} = {self._value:#x}") + + +class Registers: + def __init__(self, elf, arch=None): + """ + Registers class to store register information + + :param arch: architecture name, or use current gdb architecture by default + """ + # if we don't have register names in elf, fallback to hardcoded register layouts + if not arch: + raise ValueError("Architecture is required to get register names") + + self.logger = logging.getLogger(__name__) + self.arch = arch + self._registers = [] + regsize = utils.get_pointer_size(elf) + reginfo = utils.get_reginfo(elf) + layouts = g_reg_table.get(self.arch, {}).get("registers", []) + regoffsets = [r.tcb_offset for r in reginfo if r.tcb_offset != UINT16_MAX] + for i, (name, regnum, offset, *fixed) in enumerate(layouts): + register = Register( + name=name, + regnum=regnum, + size=regsize, + offset=offset, + tcb_reg_off=regoffsets[i] if i < len(regoffsets) else 0, + fixedvalue=fixed[0] if fixed else None, + ) + + self._registers.append(register) + self.logger.debug( + f"Register {name}({regnum}) offset: {offset}, tcb_off: {register.tcb_reg_off}" + ) + + self._registers.sort(key=lambda x: x.regnum) + + def __str__(self): + return f"({self.arch} x{len(self._registers)}, {self.sizeof()} bytes)" + + def __repr__(self): + return f"({self.arch} x{len(self._registers)}, {self.sizeof()} bytes)" + + def sizeof(self): + """Return total register size in byte""" + return sum(r.size for r in self._registers) + + def get(self, regnum: int = None, name: str = None) -> Register: + """Get register by register number""" + for reg in self._registers: + if reg.regnum == regnum: + return reg + + if reg.name == name: + return reg + + return None + + def set(self, value: Union[int, bytes], regnum: int = None, name: str = None): + """Set register value by register number""" + reg = self.get(regnum=regnum, name=name) + if not reg: + raise KeyError(f"Register {name or regnum} not found") + reg.value = value + + def load(self, xcpregs: bytes = None): + """ + Load register values from various sources. + + :param tcb: load register values from tcb.xcp.regs + :param address: load register values from specified address which points to regs in context + """ + + if xcpregs: + for reg in self._registers: + reg.value = xcpregs[reg.tcb_reg_off : reg.tcb_reg_off + reg.size] + else: + raise ValueError("No valid source to load register values") + + return self # allow to build and use Register().load() directly + + def __iter__(self): + return iter(self._registers) + + def __len__(self): + return len(self._registers) + + def __getitem__(self, key): + return self._registers[key] diff --git a/tools/pynuttx/nxstub/target.py b/tools/pynuttx/nxstub/target.py new file mode 100644 index 00000000000..3e27319d310 --- /dev/null +++ b/tools/pynuttx/nxstub/target.py @@ -0,0 +1,228 @@ +############################################################################ +# tools/pynuttx/nxstub/target.py +# +# SPDX-License-Identifier: Apache-2.0 +# +# Licensed to the Apache Software Foundation (ASF) under one or more +# contributor license agreements. See the NOTICE file distributed with +# this work for additional information regarding copyright ownership. The +# ASF licenses this file to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance with the +# License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# +############################################################################ + +import logging +import traceback +from typing import List + +from . import utils +from .registers import Registers + + +class RawMemory: + def __init__(self, address: int, data: bytearray): + self.address = address + self.data = bytearray(data) + + def __len__(self): + return len(self.data) + + def __str__(self): + return f"Memory({self.address:#x}~{self.address + len(self.data):#x})" + + def __repr__(self): + return self.__str__() + + +class ThreadInfo: + def __init__(self, name, pid, state, registers: Registers): + self.name = name + self.pid = pid + self.state = state + self.registers = registers + + def __str__(self): + return f"{self.name}({self.pid}) {self.state}" + + def __repr__(self): + return f"Thread({self.name}, {self.pid}, {self.state})" + + +class Target: + PID0_ID = 0xFFFF + + def __init__( + self, + elf, + arch=None, + registers: Registers = None, + memories: List[RawMemory] = None, + core=None, + ): + """ + The target that GDB stub operations on. + :param elf: The ELF file path. + :param registers: The optional initial register value, normally used for crash log analysis. + :param memories: The optional initial memory regions, normally used for raw memory dump. + :param arch: The architecture of the target, e.g. "arm", "riscv", "mips", etc. + """ + self.logger = logging.getLogger(__name__) + self.elf = elf + self.core = core + self.registers = registers or Registers(elf, arch=arch) + self.memories = [] + self.arch = arch + self.pid = 0 # Current thread PID + + for mem in memories or []: + # Go through the write process to merge overlapping memory regions + self.memory_write(mem.address, mem.data) + + self.logger.debug(f"Memory regions: {self.memories}") + + def _read_symbol(self, symbol: str, length: int = 0) -> bytes: + sym = utils.get_symbol(self.elf, symbol) + data = self.memory_read(sym.value, length or sym.size) + return data, sym + + def _read_int(self, symbol: str) -> int: + inttype = utils.get_inttype(self.elf) + data, sym = self._read_symbol(symbol, inttype.sizeof()) + if not data: + return None, sym + return inttype.parse(data), sym + + def _read_str(self, address: int) -> str: + output = b"" + while (b := self.memory_read(address, 1)) != b"\0": + output += b + address += 1 + + return output.decode("utf-8") + + def update_threads(self) -> List[ThreadInfo]: + """Update the latest threads information""" + + self.threads = (ThreadInfo("main", self.PID0_ID, "Running", self.registers),) + + try: + pointer = utils.get_pointer_type(self.elf) + tcbsize = utils.get_tcb_size(self.elf) + tcbinfo = utils.get_tcbinfo(self.elf) + states = utils.get_statenames(self.elf) + + g_npidhash, sym = self._read_int("g_npidhash") + self.logger.debug(f"g_npidhash: {g_npidhash}@{sym.value:#x}") + if not g_npidhash: + self.logger.error(f"No threads info found: {g_npidhash}") + return self.threads + + def parse_tcb(address: int) -> ThreadInfo: + data = self.memory_read(address, tcbsize) + if tcbinfo.name_off == 0: + name = "" + else: + name = self._read_str(address + tcbinfo.name_off) + self.logger.debug(f"loading thread: {name}") + pid = utils.uint16_t(data[tcbinfo.pid_off : tcbinfo.pid_off + 2]) + pid = pid if pid != 0 else self.PID0_ID + state = utils.uint8_t(data[tcbinfo.state_off : tcbinfo.state_off + 1]) + state = states[state] if state < len(states) else "Unknown" + registers = Registers(self.elf, arch=self.arch) + xcpregs = data[tcbinfo.regs_off : tcbinfo.regs_off + pointer.sizeof()] + xcpregs = pointer.parse(xcpregs) + xcpregs = self.memory_read(xcpregs, utils.get_regsize(self.elf)) + registers.load(xcpregs=xcpregs) + self.logger.debug(f"Parse TCB: {name}({pid},{state})") + return ThreadInfo(name, pid, state, registers) + + data, sym = self._read_symbol("g_pidhash") + g_pidhash = pointer.parse(data) + data = self.memory_read(g_pidhash, pointer.sizeof() * g_npidhash) + g_pidhash = utils.parse_array(data, pointer, g_npidhash) + self.logger.debug(f"g_pidhash: {g_pidhash}@{sym.value:#x}") + + self.threads = [parse_tcb(tcb) for tcb in g_pidhash if tcb] + self.logger.debug(f"Found {self.threads}") + except Exception as e: + self.logger.error(f"No threads info: {e}\n{traceback.format_exc()}") + + return self.threads + + def switch_thread(self, pid: int = None) -> Registers: + """ + Switch to the thread with PID, or the next running thread. + Return the registers for the thread + """ + self.logger.debug(f"Switch to thread {pid}") + pid = pid if pid is not None and pid > 0 else self.PID0_ID + + for t in self.threads: + if pid == t.pid: + self.pid = pid + self.registers = t.registers + return self.registers + + def memory_read(self, address: int, length: int) -> bytes: + self.logger.debug(f"Read: {address:#x} {length}Bytes") + # Try cached memory + for mem in self.memories: + if mem.address <= address < mem.address + len(mem): + offset = address - mem.address + # Limit the length to available data + length = min(length, len(mem) - offset) + return mem.data[offset : offset + length] + + # Try core + if self.core and (value := utils.read_from(self.core, address, length)): + return bytes(value) + + # Try elf + return bytes(utils.read_from(self.elf, address, length) or []) + + def memory_write(self, address, data): + memories = self.memories + mem = RawMemory(address, bytearray(data)) + self.logger.debug(f"Write: {mem}") + + if not memories or address > memories[-1].address + len(memories[-1]): + memories.append(mem) # New memory region in the end + return + elif address + len(data) < memories[0].address: + memories.insert(0, mem) # New memory region in the beginning + return + + for i, m in enumerate(memories): + if address > m.address + len(m): + continue + + if address + len(data) < m.address: + memories.insert(i, mem) # New memory region in the middle + return + + if (offset := address - m.address) >= 0: + # Overwrite and append data to existing memory + m.data[offset : offset + len(data)] = data + else: + # Prepend data to existing memory + offset = address + len(m) - m.address + m.data = data + m.data[offset:] + m.address = address + + # Remove overlapping memory regions + end = m.address + len(m) + for m2 in memories[i + 1 :]: + if end < m2.address: + break + + memories.remove(m2) + m.data += m2.data[end - m2.address :] diff --git a/tools/pynuttx/nxstub/utils.py b/tools/pynuttx/nxstub/utils.py new file mode 100644 index 00000000000..25d96d09bde --- /dev/null +++ b/tools/pynuttx/nxstub/utils.py @@ -0,0 +1,214 @@ +############################################################################ +# tools/pynuttx/nxstub/utils.py +# +# Licensed to the Apache Software Foundation (ASF) under one or more +# contributor license agreements. See the NOTICE file distributed with +# this work for additional information regarding copyright ownership. The +# ASF licenses this file to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance with the +# License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# +############################################################################ + +try: + import lief + from construct import ( + Array, + Construct, + Int8ul, + Int16ul, + Int32sb, + Int32sl, + Int32ub, + Int32ul, + Int64sb, + Int64sl, + Int64ub, + Int64ul, + Struct, + ) +except ImportError: + print('Package missing, please do "pip install lief construct"') + +import logging +from typing import List, Tuple + + +class RegInfo: + def __init__(self, name, size, tcb_offset=0): + self.name = name + self.size = size + self.tcb_offset = tcb_offset + + def __str__(self): + return f"{self.name}({self.size})" + + def __repr__(self): + return f"REG({self.name}, {self.size}, {self.tcb_offset})" + + +def parse_elf(elf_file: str) -> lief.Binary: + elf = lief.parse(elf_file) + + if not elf: + logging.error(f"Failed to parse ELF file: {elf_file}") + return None + + return elf.abstract + + +def get_architecture(elf: lief.Binary): + return elf.header.architecture + + +def get_endian(elf: lief.Binary) -> str: + return "l" if elf.header.endianness == lief.Header.ENDIANNESS.LITTLE else "b" + + +def read_from(elf: lief.Binary, addr, len=1) -> memoryview: + # For xtensa elf, read directly returns wrong value, manually parse the section in this case. + + for section in elf.sections: + if section.type == lief.ELF.Section.TYPE.PROGBITS: + if section.virtual_address <= addr < section.virtual_address + section.size: + off = addr - section.virtual_address + return section.content[off : off + len] + + if data := elf.get_content_from_virtual_address(addr, len): + return data + + return None + + +def get_symbol(elf: lief.Binary, symbol) -> lief.Symbol: + return elf.get_symbol(symbol) + + +def read_symbol( + elf: lief.Binary, symbol, struct: Construct = None +) -> Tuple[lief.Symbol, memoryview]: + sym = elf.get_symbol(symbol) + if sym is None: + return None + + data = read_from(elf, sym.value, sym.size) + if struct: + data = struct.parse(data) + return sym, data + + +def read_string(elf: lief.Binary, addr): + """Read const string from ELF file""" + output = b"" + while True: + c = read_from(elf, addr, 1) + if c == b"\0": + break + + output += c.tobytes() + addr += 1 + + return output.decode("utf-8") + + +def get_inttype(elf: lief.Binary) -> Construct: + endian = get_endian(elf) + bits = 64 if elf.header.is_64 else 32 + return { + "32l": Int32sl, + "32b": Int32sb, + "64l": Int64sl, + "64b": Int64sb, + }.get(f"{bits}{endian}", Int32sl) + + +def get_pointer_type(elf: lief.Binary) -> Construct: + endian = get_endian(elf) + bits = 64 if elf.header.is_64 else 32 + return { + "32l": Int32ul, + "32b": Int32ub, + "64l": Int64ul, + "64b": Int64ub, + }.get(f"{bits}{endian}", Int32ul) + + +def get_pointer_size(elf: lief.Binary): + return 8 if elf.header.is_64 else 4 + + +def get_ncpus(elf: lief.Binary) -> int: + # FAR struct tcb_s *g_running_tasks[CONFIG_SMP_NCPUS]; + # + # g_running_tasks is an pointer array in length of ncpu + g_running_tasks = elf.get_symbol("g_running_tasks") + + return g_running_tasks.size // get_pointer_size(elf) + + +def get_regsize(elf: lief.Binary) -> int: + """Register size in context""" + sym = elf.get_symbol("g_last_regs") + return sym.size // get_ncpus(elf) + + +def get_tcbinfo(elf: lief.Binary): + tcbinfo_s = Struct( + "pid_off" / Int16ul, # FIXME: only little endian supported + "state_off" / Int16ul, + "pri_off" / Int16ul, + "name_off" / Int16ul, + "stack_off" / Int16ul, + "stack_size_off" / Int16ul, + "regs_off" / Int16ul, + "regs_num" / Int16ul, + ) + + _, data = read_symbol(elf, "g_tcbinfo") + return tcbinfo_s.parse(data) + + +def get_tcb_size(elf: lief.Binary) -> int: + # static struct tcb_s g_idletcb[CONFIG_SMP_NCPUS]; + # Idle TCB happen to be an array of tcb_s + + g_idletcb = elf.get_symbol("g_idletcb") + ncpus = get_ncpus(elf) + return g_idletcb.size // ncpus + + +def get_reginfo(elf: lief.Binary) -> List[RegInfo]: + bits = 64 if elf.header.is_64 else 32 + + # Now get register offset in TCB + _, data = read_symbol(elf, "g_reg_offs") + reg_offs = Array(len(data) // 2, Int16ul).parse(data) + return [RegInfo("", bits // 8, off) for off in reg_offs] + + +def parse_array(data, type_, narray): + return Array(narray, type_).parse(data) + + +def get_statenames(elf: lief.Binary) -> List[str]: + pointer = get_pointer_type(elf) + sym, addr = read_symbol(elf, "g_statenames") + names = parse_array(addr, pointer, sym.size // pointer.sizeof()) + names = [read_string(elf, name) for name in names] + return names + + +def uint16_t(data: bytes) -> int: + return Int16ul.parse(data) + + +def uint8_t(data: bytes) -> int: + return Int8ul.parse(data) diff --git a/tools/pynuttx/setup.py b/tools/pynuttx/setup.py index 844e5dc5de9..2328d1670b2 100644 --- a/tools/pynuttx/setup.py +++ b/tools/pynuttx/setup.py @@ -1,14 +1,19 @@ from setuptools import find_packages, setup setup( - name="pynuttx", + name="pynuttxtest", version="0.0.1", - packages=find_packages(include=["nxgdb", "nxelf"]), + packages=find_packages(include=["nx*"]), install_requires=[], description="NuttX python development tools", + entry_points={ + "console_scripts": [ + "nxstub = nxstub.__main__:main", + ], + }, classifiers=[ "Programming Language :: Python :: 3", "License :: OSI Approved :: Apache Software License", ], - requires=["matplotlib", "numpy", "pyelftools", "debugpy"], + requires=["construct", "debugpy", "lief", "matplotlib", "numpy", "pyelftools"], ) -- Gitee From 26de60ac0f12103afe0b6d01a13cbf794bd08f9b Mon Sep 17 00:00:00 2001 From: xuxingliang Date: Sun, 5 Jan 2025 01:04:42 +0800 Subject: [PATCH 055/235] nxstub: add proxy mode VELAPLATFO-43422 Currently only qemu is supported. More work will be needed to support simulator, since gdbserver uses full feature of RSP protocol, intecepting only the thread command is not enough to make it running. Change-Id: I6ed919db1d7a323cbd7ee84d3497753aabdcb020 Signed-off-by: xuxingliang --- tools/pynuttx/nxstub/__init__.py | 20 +++- tools/pynuttx/nxstub/gdbstub.py | 129 +++++++++++------------ tools/pynuttx/nxstub/proxy.py | 165 ++++++++++++++++++++++++++++++ tools/pynuttx/nxstub/registers.py | 32 +++++- tools/pynuttx/nxstub/utils.py | 48 +++++++++ 5 files changed, 320 insertions(+), 74 deletions(-) create mode 100644 tools/pynuttx/nxstub/proxy.py diff --git a/tools/pynuttx/nxstub/__init__.py b/tools/pynuttx/nxstub/__init__.py index 1f9ae0a5621..c4b3bf572a9 100644 --- a/tools/pynuttx/nxstub/__init__.py +++ b/tools/pynuttx/nxstub/__init__.py @@ -31,6 +31,7 @@ from typing import List from . import utils from .gdbstub import GDBStub, Target +from .proxy import TargetProxy from .registers import Registers, g_reg_table from .target import RawMemory @@ -133,9 +134,14 @@ def gdbstub_start(args): memories.extend(mem) core = utils.parse_elf(args.core) if args.core else None - target = Target(elf, args.arch, registers, memories, core) - stub = GDBStub(target=target, port=args.port) + if args.proxy is not None: + print(f"Try proxying localhost:{args.proxy}...") + target = TargetProxy(elf, args.arch, args.proxy) + else: + target = Target(elf, args.arch, registers, memories, core) + + stub = GDBStub(target=target, port=args.port, proxymode=args.proxy is not None) print(f"Start GDB server on port {args.port}...") stub.run() @@ -186,6 +192,12 @@ def parse_args(args=None): default=1234, help="The GDB server port.", ) + parser.add_argument( + "--proxy", + type=int, + default=None, + help="The original GDB server port for proxy.", + ) parser.add_argument( "-r", "--rawfile", @@ -232,7 +244,9 @@ def main(args=None): gdb = None if args.debug: - logging.basicConfig() + logging.basicConfig( + format="%(asctime)s:%(levelname)s:%(name)s:%(message)s", + ) logger = logging.getLogger(__name__) logger.setLevel(logging.DEBUG if args.debug else logging.INFO) diff --git a/tools/pynuttx/nxstub/gdbstub.py b/tools/pynuttx/nxstub/gdbstub.py index 7e9d42d26d0..8eda323eb5a 100644 --- a/tools/pynuttx/nxstub/gdbstub.py +++ b/tools/pynuttx/nxstub/gdbstub.py @@ -26,6 +26,7 @@ import traceback from binascii import hexlify, unhexlify from typing import Union +from . import utils from .target import Target @@ -34,7 +35,9 @@ class GDBStub: self, target: Target, port=1234, + proxymode=False, ): + self.proxymode = proxymode self.threads = target.update_threads() self.registers = target.switch_thread() self.target = target @@ -50,12 +53,19 @@ class GDBStub: while not self.exiting: try: - packet = self.get_packet() + packet = utils.get_packet(self.socket) + if packet in b"+-": + continue + + self.socket.send(b"+") if packet is None: self.logger.info("Connection closed") return - self.process_packet(packet) + if self.proxymode: + self.forward_packet(packet) + else: + self.process_packet(packet) except Exception as e: self.logger.error(f"Error in stub thread: {e} {traceback.format_exc()}") @@ -82,50 +92,6 @@ class GDBStub: listener.close() return client - def get_packet(self) -> Union[bytes, None]: - buffer = bytearray() - started = False - escaping = False - checksum = 0 - while True: - c = self.socket.recv(1) - if not started: - if c == b"\x03": - return b"\x03" - if c == b"$": - started = True - continue - - if escaping: - c ^= 0x20 - escaping = False - elif c == b"}": - escaping = True - checksum += ord(c) - continue - - if c == b"#": - expected = self.socket.recv(2) - expected = int(expected.decode("ascii"), 16) - if expected != checksum & 0xFF: - self.logger.error( - f"checksum error: {expected:#x} != {checksum & 0xFF:#x}" - ) - self.socket.send(b"-") # No ack - checksum = 0 - started = False - buffer = bytearray() - continue - else: - self.socket.send(b"+") - break - else: - checksum += ord(c) - buffer.append(ord(c)) - - self.logger.debug(f"Received packet: {buffer}") - return bytes(buffer) - def send_raw_packet(self, data: bytes, nowait=False) -> bool: checksum = sum(data) & 0xFF self.socket.send(b"$") @@ -142,13 +108,8 @@ class GDBStub: if isinstance(packet, str): packet = packet.encode("ascii") - output = list() - for c in packet: - if c in b"$#*}": - output.append(ord("}")) - c ^= 0x20 - output.append(c) - return self.send_raw_packet(bytes(output), nowait) + output = utils.encode_packet(packet) + return self.send_raw_packet(output, nowait) def send_unsupported(self): self.send_packet("") @@ -173,6 +134,28 @@ class GDBStub: self.logger.error(f"Error packet{packet}: {e}\n {traceback.format_exc()}") self.send_packet("EF1") + def forward_packet(self, packet: bytes): + packet_type = packet[0] + if packet_type in b"iIzZsSmMxX": + try: + self.logger.debug(f"Forwarding packet: {packet[:20]}...") + response = self.target.send_packet(packet) + self.logger.debug(f"Received response: {response and response[:20]}...") + except Exception as e: + self.logger.error(f"Error forwarding packet: {e}") + return + + if response: + # The response is the raw packet received via RSP, excluding start, end and checksum + self.send_raw_packet(response, nowait=True) + else: + self.send_packet("") + elif packet_type in b"?vqgpPTHc\x03D": + self.process_packet(packet) + else: + self.logger.debug(f"Ignore packet: {packet}") + self.send_unsupported() + def handle_q(self, packet: bytes): packet = packet.decode("ascii") if packet.startswith("qSupported"): @@ -202,22 +185,15 @@ class GDBStub: self.send_unsupported() def handle_questionmark(self, packet: bytes): - self.send_packet("S05") + running = next((t for t in self.threads if t.state == "Running"), None) + if running: + self.registers = self.target.switch_thread(running.pid) + self.send_packet(f"T02thread:{running.pid:x};") + else: + self.send_packet("S05") def handle_g(self, packet: bytes): - reply = b"" - offset = 0 - for reg in self.registers: - if reg.offset and reg.offset != offset: - reply += b"xx" * (reg.offset - offset) - - if not reg.has_value: - reply += b"xx" * reg.size - else: - reply += hexlify(bytes(reg)) - - offset += reg.offset + reg.size - self.send_packet(reply) + self.send_packet(self.registers.to_g()) def handle_p(self, packet: bytes): packet = packet.decode("ascii") @@ -248,9 +224,11 @@ class GDBStub: self.send_packet("OK" if ok else "") def handle_etx(self, packet: bytes): - # FIXME no reply needed - self.send_packet("S00") self.logger.info("Ctrl-C received") + if self.proxymode: + self.target.stop() + else: + self.send_packet("S00") def handle_k(self, packet: bytes): self.exiting = True @@ -267,3 +245,16 @@ class GDBStub: return self.registers = registers self.send_packet("OK") + + def handle_c(self, packet): + if hasattr(self.target, "cont"): + + def stopped(stopreason): + # FIXME callback from another thread + self.logger.info(f"Target stopped: {stopreason}") + self.handle_questionmark(None) + + # Notify the stub when it's stopped + self.target.cont(stopped) + else: + self.send_unsupported() diff --git a/tools/pynuttx/nxstub/proxy.py b/tools/pynuttx/nxstub/proxy.py new file mode 100644 index 00000000000..47b2a08c840 --- /dev/null +++ b/tools/pynuttx/nxstub/proxy.py @@ -0,0 +1,165 @@ +############################################################################ +# tools/pynuttx/nxstub/proxy.py +# +# SPDX-License-Identifier: Apache-2.0 +# +# Licensed to the Apache Software Foundation (ASF) under one or more +# contributor license agreements. See the NOTICE file distributed with +# this work for additional information regarding copyright ownership. The +# ASF licenses this file to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance with the +# License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# +############################################################################ + +import atexit +import logging +import queue +import socket +import threading +from binascii import unhexlify + +from . import utils +from .target import Target + + +class TargetProxy(Target): + def __init__(self, elf, arch=None, port=None): + super().__init__(elf, arch=arch) + self.exit = False + self.logger = logging.getLogger(__name__) + + def send_thread(queue: queue.Queue, sock: socket.socket): + while not self.exit: + packet = queue.get() + self.logger.debug(f"Send: {packet}") + sock.send(packet) + self.logger.debug("Sent.") + + def recv_thread(queue: queue.Queue, sock: socket.socket): + while not self.exit: + packet = utils.get_packet(sock) + queue.put(packet) + self.logger.debug(f"Received: {packet}") + + sock = self.connect_target(port) + self.txqueue = queue.Queue() + self.rxqueue = queue.Queue() + self.sender = threading.Thread(target=send_thread, args=(self.txqueue, sock)) + self.receiver = threading.Thread(target=recv_thread, args=(self.rxqueue, sock)) + + self.sender.start() + self.receiver.start() + + self.clear_rxqueue() + atexit.register(self.__del__) + + def __del__(self): + self.logger.warning("Destructor called") + self.exit = True + self.txqueue.put(None) + self.rxqueue.put(None) + self.sender.join() + self.receiver.join() + + def connect_target(self, port): + target = socket.socket(socket.AF_INET, socket.SOCK_STREAM) + target.connect(("localhost", port)) + self.logger.info(f"Connected to target: localhost:{port}") + return target + + def clear_rxqueue(self): + while (packet := self.receive_packet(block=False)) is not None: + self.logger.debug(f"Clearing queue: {packet}") + + def send_packet(self, packet, timeout=None, noresponse=False): + encoded = utils.encode_packet(packet) + checksum = sum(encoded) & 0xFF + encoded = b"$" + encoded + b"#" + b"%02x" % checksum + + self.clear_rxqueue() + self.txqueue.put(encoded) + ack = self.receive_packet(timeout) + if ack != b"+": + self.logger.warning(f"Not ack received: {ack}, try again...") + ack = self.receive_packet(timeout=1) + if ack != b"+": + self.logger.error(f"Failed to send packet: {packet}, get ack: '{ack}'") + return + + self.logger.debug(f"Sent packet: {packet}") + if noresponse: + return + + response = self.receive_packet(timeout) + self.logger.debug(f"Target response: {response}") + return response + + def receive_packet(self, timeout=1, block=True): + try: + return self.rxqueue.get(block=block, timeout=timeout) + except queue.Empty: + return None + + def memory_read(self, address: int, length: int) -> bytes: + self.logger.debug(f"Read target: {address:#x} {length}Bytes") + response = self.send_packet(b"m%x,%x" % (address, length)) + data = unhexlify(response) + return data + + def memory_write(self, address, data): + # We do not support write for now for debug purpose + self.logger.warning(f"Ignore write target: {address:#x} {len(data)}Bytes") + pass + + def read_registers(self): + response = self.send_packet(b"g") + response = unhexlify(response) + self.logger.debug(f"Raw registers: {response}") + return response + + def update_threads(self): + threads = super().update_threads() + # Since we are doing live debugging, we need to correct the registers of running threads + for t in threads: + if t.state == "Running": + t.registers.from_g(self.read_registers()) + break + return threads + + def cont(self, callback): + self.send_packet(b"c", noresponse=True) # continue packet has no response + + self.running = True + + def checker(callback): + self.logger.debug("Cont checker started, waiting for response...") + while self.running: + self.logger.debug("Checking...") + if response := self.receive_packet(timeout=0.1): + self.logger.debug(f"Cont got response: {response}") + self.running = False + self.send_packet(b"z0") + self.update_threads() + callback(response) + return + + self.logger.error(f"Cont checker stopped, target: {self.state}") + + threading.Thread(target=checker, args=(callback,)).start() + + def stop(self): + # Send a break signal, instead of a full packet. + self.txqueue.put(b"\x03") + + def forward_packet(self, packet): + self.txqueue.put(packet) + return self.receive_packet() diff --git a/tools/pynuttx/nxstub/registers.py b/tools/pynuttx/nxstub/registers.py index 61b12e41277..72bb900ec9e 100644 --- a/tools/pynuttx/nxstub/registers.py +++ b/tools/pynuttx/nxstub/registers.py @@ -21,7 +21,8 @@ ############################################################################ import logging -from typing import Union +from binascii import hexlify +from typing import List, Union from . import utils @@ -280,7 +281,7 @@ class Registers: self.logger = logging.getLogger(__name__) self.arch = arch - self._registers = [] + self._registers: List[Register] = [] regsize = utils.get_pointer_size(elf) reginfo = utils.get_reginfo(elf) layouts = g_reg_table.get(self.arch, {}).get("registers", []) @@ -346,6 +347,33 @@ class Registers: return self # allow to build and use Register().load() directly + def to_g(self): + """Return GDB RSP g packet""" + reply = b"" + offset = 0 + for reg in self._registers: + if reg.offset and reg.offset != offset: + reply += b"xx" * (reg.offset - offset) + + if not reg.has_value: + reply += b"xx" * reg.size + else: + reply += hexlify(bytes(reg)) + + offset += reg.offset + reg.size + return reply + + def from_g(self, data: bytes): + """Parse GDB RSP G packet""" + offset = 0 + for reg in self._registers: + offset = reg.offset if reg.offset else offset + self.logger.debug( + f"Parse {reg.name}({reg.regnum}) from {offset}, data: {data[offset:offset+reg.size]}" + ) + reg.value = data[offset : offset + reg.size] + offset += reg.size + def __iter__(self): return iter(self._registers) diff --git a/tools/pynuttx/nxstub/utils.py b/tools/pynuttx/nxstub/utils.py index 25d96d09bde..84282d6da7c 100644 --- a/tools/pynuttx/nxstub/utils.py +++ b/tools/pynuttx/nxstub/utils.py @@ -212,3 +212,51 @@ def uint16_t(data: bytes) -> int: def uint8_t(data: bytes) -> int: return Int8ul.parse(data) + + +def get_packet(sock) -> bytes: + buffer = bytearray() + started = False + escaping = False + checksum = 0 + while True: + c = sock.recv(1) + if not started: + if c in (b"\x03", b"+", b"-"): # Special packets + return c + if c == b"$": + started = True + continue + + if escaping: + c = chr(ord(c) ^ 0x20) + escaping = False + elif c == b"}": + escaping = True + checksum += ord(c) + continue + + if c == b"#": + expected = sock.recv(2) + expected = int(expected.decode("ascii"), 16) + if expected != checksum & 0xFF: + checksum = 0 + started = False + buffer = bytearray() + continue + else: + break + else: + checksum += ord(c) + buffer.append(ord(c)) + return buffer + + +def encode_packet(packet: bytes) -> bytes: + output = list() + for c in packet: + if c in b"$#*}": + output.append(ord("}")) + c ^= 0x20 + output.append(c) + return bytes(output) -- Gitee From 8d473ac7e0c1dc49c071819d8aa631b74ef72d5f Mon Sep 17 00:00:00 2001 From: xuxingliang Date: Mon, 6 Jan 2025 00:40:13 +0800 Subject: [PATCH 056/235] nxgdb: add nxstub to GDB command VELAPLATFO-43422 Now we can start the GDB stub and connect to it directly from GDB. E.g. xtensa-esp32s3-elf-gdb gdbstubtest/xtensa/vela_audio.elf -ex "source nuttx/tools/pynuttx/gdbinit.py" (gdb)tar stub -c gdbstubtest/xtensa/568f842ad65-dirt-6769b4a4.core Start GDB server on port 1234... Remote debugging using :1234 up_idle () at chip/bes_chip.c:204 warning: 204 chip/bes_chip.c: No such file or directory (gdb) Change-Id: I0447eae67b1bb1760a903d189981d33a195b2c95 Signed-off-by: xuxingliang --- tools/pynuttx/nxgdb/target.py | 78 +++++++++++++++++++++++++++++++++++ tools/pynuttx/nxgdb/thread.py | 7 +--- 2 files changed, 79 insertions(+), 6 deletions(-) create mode 100644 tools/pynuttx/nxgdb/target.py diff --git a/tools/pynuttx/nxgdb/target.py b/tools/pynuttx/nxgdb/target.py new file mode 100644 index 00000000000..bb64d22ffee --- /dev/null +++ b/tools/pynuttx/nxgdb/target.py @@ -0,0 +1,78 @@ +############################################################################ +# tools/pynuttx/nxgdb/target.py +# +# SPDX-License-Identifier: Apache-2.0 +# +# Licensed to the Apache Software Foundation (ASF) under one or more +# contributor license agreements. See the NOTICE file distributed with +# this work for additional information regarding copyright ownership. The +# ASF licenses this file to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance with the +# License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# +############################################################################ + +import multiprocessing + +import gdb +import nxstub + + +class Target(gdb.Command): + """Use nxstub to parse crash log dump, core dump or memory dump, as target.""" + + def __init__(self): + super().__init__("target stub", gdb.COMMAND_USER) + self.process = None + + def invoke(self, args, from_tty): + self.dont_repeat() + + if "-e" not in args and "--elf" not in args: + args += f" -e {gdb.objfiles()[0].filename}" + + if "-a" not in args and "--arch" not in args: + args += f" -a {gdb.selected_inferior().architecture().name().lower()}" + + # If currently has connection to target, disconnect it + inferior = gdb.selected_inferior() + if inferior and inferior.connection and inferior.connection.is_valid(): + gdb.execute("disconnect") + + def kill(event=None): + if self.process: + self.process.kill() + self.process.join() + self.process = None + print("nxstub process killed") + + if self.process: + y = input("nxstub process already running, kill it? [y/n] ") + if y.lower() != "y": + return + + kill() + + args = gdb.string_to_argv(args) + process = multiprocessing.Process(target=nxstub.main, args=(args,)) + process.start() + self.process = process + + gdb.events.gdb_exiting.connect(kill) + print("") + + # Wait server to start + try: + parsed = nxstub.parse_args(args) + except SystemExit: + return + + gdb.execute(f"target remote :{parsed.port}", from_tty=True) diff --git a/tools/pynuttx/nxgdb/thread.py b/tools/pynuttx/nxgdb/thread.py index 359d75cdefd..023edbc4949 100644 --- a/tools/pynuttx/nxgdb/thread.py +++ b/tools/pynuttx/nxgdb/thread.py @@ -210,8 +210,6 @@ class Nxinfothreads(gdb.Command): def __init__(self): super().__init__("info nxthreads", gdb.COMMAND_USER) - if not is_thread_command_supported(): - gdb.execute("define info threads\n info nxthreads \n end\n") def invoke(self, args, from_tty): npidhash = gdb.parse_and_eval("g_npidhash") @@ -301,10 +299,7 @@ class Nxthread(gdb.Command): """Switch to a specified thread""" def __init__(self): - if not is_thread_command_supported(): - super().__init__("thread", gdb.COMMAND_USER) - else: - super().__init__("nxthread", gdb.COMMAND_USER) + super().__init__("nxthread", gdb.COMMAND_USER) def invoke(self, args, from_tty): npidhash = gdb.parse_and_eval("g_npidhash") -- Gitee From 8d24021d384ba4f4b4948369826f01a47be5bc2f Mon Sep 17 00:00:00 2001 From: xuxingliang Date: Fri, 10 Jan 2025 12:59:16 +0800 Subject: [PATCH 057/235] nxgdb/tests: fix thread related tests VELAPLATFO-43422 We should use info nxthreads, and nxthread correpondingly if thread awareness support is not sure. In this way, when the new target like `target stub` support thread awareness, we can use info threads. Hard wire info thread to info nxthread makes it impossible. Change-Id: I22b2ffcad68a707f18cad7f5cb29791485a3ffe4 Signed-off-by: xuxingliang --- tools/pynuttx/tests/test_runtime_thread.py | 28 +++++++++++----------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/tools/pynuttx/tests/test_runtime_thread.py b/tools/pynuttx/tests/test_runtime_thread.py index 28a72a4ae72..33d23988a52 100644 --- a/tools/pynuttx/tests/test_runtime_thread.py +++ b/tools/pynuttx/tests/test_runtime_thread.py @@ -33,36 +33,36 @@ class TestThread(unittest.TestCase): pass def test_info_threads(self): - gdb.execute("info threads") + gdb.execute("info nxthreads") def test_thread(self): - gdb.execute("thread") + gdb.execute("nxthread") def test_thread_bad_args(self): - out = gdb.execute("thread apply", to_string=True) + out = gdb.execute("nxthread apply", to_string=True) self.assertEqual(out, "Please specify a thread ID list\n") - out = gdb.execute("thread apply bad", to_string=True) + out = gdb.execute("nxthread apply bad", to_string=True) self.assertEqual(out, "Please specify a command following the thread ID list\n") - out = gdb.execute("thread apply badid0 cmd", to_string=True) + out = gdb.execute("nxthread apply badid0 cmd", to_string=True) self.assertEqual(out, "Please specify a thread ID list and command\n") - out = gdb.execute("thread badid", to_string=True) + out = gdb.execute("nxthread badid", to_string=True) self.assertEqual(out, "Invalid thread id badid\n") - out = gdb.execute("thread 256", to_string=True) + out = gdb.execute("nxthread 256", to_string=True) self.assertEqual(out, "Invalid thread id 256\n") def test_thread_apply_all(self): - out = gdb.execute("thread apply all bt", to_string=True) + out = gdb.execute("nxthread apply all bt", to_string=True) self.assertTrue("#0" in out and "Thread" in out, msg=f"Got: {out}") def test_thread_apply_with_ids(self): - out = gdb.execute("thread apply 0 bt", to_string=True) + out = gdb.execute("nxthread apply 0 bt", to_string=True) self.assertTrue("#0" in out and "Thread 0" in out, msg=f"Got: {out}") - out = gdb.execute("thread apply 0 1 info reg", to_string=True) + out = gdb.execute("nxthread apply 0 1 info reg", to_string=True) # info reg has format like # reg xxx xxx self.assertGreaterEqual(len(out.split("\n")[0].split()), 2, msg=f"Got: {out}") @@ -71,7 +71,7 @@ class TestThread(unittest.TestCase): # This command suppose to switch the stack frames # make sure we have at least two threads if gdb.parse_and_eval("g_npidhash") < 2: - out = gdb.execute("thread 0", to_string=True) + out = gdb.execute("nxthread 0", to_string=True) self.assertEqual(out, "") return @@ -82,13 +82,13 @@ class TestThread(unittest.TestCase): cur_thread_id = gdb.parse_and_eval("g_running_tasks")["pid"] - gdb.execute("thread 0") + gdb.execute("nxthread 0") gdb.execute("frame 0") cur_sp = utils.get_sp() sps = [] for i in range(gdb.parse_and_eval("g_npidhash")): - gdb.execute(f"thread {i}") + gdb.execute(f"nxthread {i}") # switch frame here gdb.execute("frame 0") new_sp = utils.get_sp() @@ -97,4 +97,4 @@ class TestThread(unittest.TestCase): # We should have some different stack pointers self.assertFalse(all([int(sp) == int(cur_sp) for sp in sps])) - gdb.execute(f"thread {cur_thread_id}") + gdb.execute(f"nxthread {cur_thread_id}") -- Gitee From daa4eb397bec733d68f483e3a14471394060ff50 Mon Sep 17 00:00:00 2001 From: xuxingliang Date: Fri, 10 Jan 2025 23:16:38 +0800 Subject: [PATCH 058/235] nxgdb/mm: fix regular expression to parse log VELAPLATFO-52029 There could be only one space ahead of address. Change-Id: I9695b8967a0a8073220eb2307beb021ab47f6f2d Signed-off-by: xuxingliang --- tools/pynuttx/nxgdb/memdump.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/pynuttx/nxgdb/memdump.py b/tools/pynuttx/nxgdb/memdump.py index 2b42ae199c5..8374b0cd9a8 100644 --- a/tools/pynuttx/nxgdb/memdump.py +++ b/tools/pynuttx/nxgdb/memdump.py @@ -190,7 +190,7 @@ def parse_memdump_log(logfile, filters=None) -> Generator[MMNodeDump, None, None with open(logfile) as f: for line in f: match = re.search( - r"\s+(\d+)\s+(\d+)\s+(\d+)\s+(\d+)\s+((?:\s+0x[0-9a-fA-F]+)+)", line + r"(\d+)\s+(\d+)\s+(\d+)\s+(\d+)((?:\s+0x[0-9a-fA-F]+)+)", line ) if not match: continue -- Gitee From 7d376fb30fc8ab4defb4faca0f2fda0189adb2f2 Mon Sep 17 00:00:00 2001 From: xuxingliang Date: Fri, 10 Jan 2025 22:31:31 +0800 Subject: [PATCH 059/235] nxgdb: fix mm.CONFIG_MM_BACKTRACE parse error VELAPLATFO-52029 It has been reported several times that the macro parsing returns wrong value, due to readelf results include two values for same macro. We use type mm_freenode_s here to check the value of MM_BACKTRACE which is more straightforward and reliable. Do the same for SEQNO. Change-Id: I90812721975b2243ca32cb3e795ed548e442ffdc Signed-off-by: xuxingliang --- tools/pynuttx/nxgdb/mm.py | 15 ++++++++++++--- tools/pynuttx/nxgdb/utils.py | 8 ++++++++ 2 files changed, 20 insertions(+), 3 deletions(-) diff --git a/tools/pynuttx/nxgdb/mm.py b/tools/pynuttx/nxgdb/mm.py index b76c78962db..9a0a7afc508 100644 --- a/tools/pynuttx/nxgdb/mm.py +++ b/tools/pynuttx/nxgdb/mm.py @@ -31,9 +31,18 @@ from . import lists, utils from .protocols import mm as p from .utils import Value -CONFIG_MM_BACKTRACE = utils.get_symbol_value("CONFIG_MM_BACKTRACE") -CONFIG_MM_BACKTRACE = -1 if CONFIG_MM_BACKTRACE is None else int(CONFIG_MM_BACKTRACE) -CONFIG_MM_BACKTRACE_SEQNO = utils.get_symbol_value("CONFIG_MM_BACKTRACE_SEQNO") +# Note we use mm_freenode_s to check if CONFIG_MM_BACKTRACE is enabled instead +# of utils.get_symbol_value("CONFIG_MM_BACKTRACE") because the latter may report +# wrong value on some platforms. + +mm_freenode_s = utils.lookup_type("struct mm_freenode_s") + +if "backtrace" in utils.get_fieldnames(mm_freenode_s): + CONFIG_MM_BACKTRACE = utils.nitems(mm_freenode_s["backtrace"]) +else: + CONFIG_MM_BACKTRACE = -1 + +CONFIG_MM_BACKTRACE_SEQNO = "seqno" in utils.get_fieldnames(mm_freenode_s) PID_MM_INVALID = -100 PID_MM_MEMPOOL = -1 diff --git a/tools/pynuttx/nxgdb/utils.py b/tools/pynuttx/nxgdb/utils.py index 114a08c05a8..390196af90e 100644 --- a/tools/pynuttx/nxgdb/utils.py +++ b/tools/pynuttx/nxgdb/utils.py @@ -240,6 +240,14 @@ def lookup_type(name, block=None) -> gdb.Type: return g_type_cache[key] +def get_fieldnames(t: gdb.Type) -> List[str]: + """Return the field names of a type""" + if isinstance(t, str): + t = lookup_type(t) + + return [f.name for f in t.fields()] + + long_type = lookup_type("long") # Common Helper Functions -- Gitee From 78759a6057385ea736fe02620e6502b80498bff0 Mon Sep 17 00:00:00 2001 From: xuxingliang Date: Thu, 9 Jan 2025 09:37:03 +0800 Subject: [PATCH 060/235] nxgdb: fix parsing stack_color macro VELAPLATFO-52029 For some platform, the function up_create_stack is not available, fallback to hardcoded value, which suits most cases. Change-Id: Ia467078db45047101f5fa75183187688df6cc41f Signed-off-by: xuxingliang --- tools/pynuttx/nxgdb/stack.py | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/tools/pynuttx/nxgdb/stack.py b/tools/pynuttx/nxgdb/stack.py index 132cb9a84d3..8d50c600aa0 100644 --- a/tools/pynuttx/nxgdb/stack.py +++ b/tools/pynuttx/nxgdb/stack.py @@ -26,9 +26,12 @@ import gdb from . import utils -STACK_COLORATION_PATTERN = utils.get_symbol_value( - "STACK_COLOR", locspec="up_create_stack" -) +try: + STACK_COLORATION_PATTERN = utils.get_symbol_value( + "STACK_COLOR", locspec="up_create_stack" + ) +except gdb.error: + STACK_COLORATION_PATTERN = 0xDEADBEEF class Stack(object): -- Gitee From fc649691de081b9240a06786efbdd1f73fd44054 Mon Sep 17 00:00:00 2001 From: xuxingliang Date: Thu, 9 Jan 2025 09:37:25 +0800 Subject: [PATCH 061/235] nxstub: task states string may get optimized out VELAPLATFO-52029 Change-Id: I61a6a6e49285fb9c00b8a42a065f078e40500a62 Signed-off-by: xuxingliang --- tools/pynuttx/nxstub/target.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/tools/pynuttx/nxstub/target.py b/tools/pynuttx/nxstub/target.py index 3e27319d310..3d093d0f078 100644 --- a/tools/pynuttx/nxstub/target.py +++ b/tools/pynuttx/nxstub/target.py @@ -118,7 +118,11 @@ class Target: pointer = utils.get_pointer_type(self.elf) tcbsize = utils.get_tcb_size(self.elf) tcbinfo = utils.get_tcbinfo(self.elf) - states = utils.get_statenames(self.elf) + try: + states = utils.get_statenames(self.elf) + except Exception: + # Fallback to pure number. Don't bother to parse value of NUM_TASK_STATES, 256 is enough. + states = [str(i) for i in range(256)] g_npidhash, sym = self._read_int("g_npidhash") self.logger.debug(f"g_npidhash: {g_npidhash}@{sym.value:#x}") -- Gitee From a5e2cb6c751c68180e09178f2d746162831fc2eb Mon Sep 17 00:00:00 2001 From: xuxingliang Date: Fri, 10 Jan 2025 16:12:23 +0800 Subject: [PATCH 062/235] nxstub: fix GDB crash when reported thread does not exist VELAPLATFO-52029 The qC command must return a valid thread ID, otherwise GDB may assert. This may happen when g_statesnames get optimized out, when we cannot get the running thread. Added `current_thread` for target, which represents current operating thread ID, which can be set by packet 'H'. Change-Id: I73851ddd1fd2b4b955944c2410b5787935bf0986 Signed-off-by: xuxingliang --- tools/pynuttx/nxstub/gdbstub.py | 4 +++- tools/pynuttx/nxstub/target.py | 5 ++++- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/tools/pynuttx/nxstub/gdbstub.py b/tools/pynuttx/nxstub/gdbstub.py index 8eda323eb5a..27a702d9233 100644 --- a/tools/pynuttx/nxstub/gdbstub.py +++ b/tools/pynuttx/nxstub/gdbstub.py @@ -161,7 +161,7 @@ class GDBStub: if packet.startswith("qSupported"): self.send_packet("PacketSize=FFFF") elif packet.startswith("qC"): - pid = next((t.pid for t in self.threads if t.state == "Running"), 0) + pid = self.target.current_thread() self.logger.debug(f"Current thread: {pid}") self.send_packet(f"QC{pid:x}") elif packet.startswith("qfThreadInfo"): @@ -186,6 +186,8 @@ class GDBStub: def handle_questionmark(self, packet: bytes): running = next((t for t in self.threads if t.state == "Running"), None) + # FIXME t.state may be a number when g_statesnames gets optimized out. + # That's fine for now since we can identify the running thread manually. if running: self.registers = self.target.switch_thread(running.pid) self.send_packet(f"T02thread:{running.pid:x};") diff --git a/tools/pynuttx/nxstub/target.py b/tools/pynuttx/nxstub/target.py index 3d093d0f078..c36a864f7c1 100644 --- a/tools/pynuttx/nxstub/target.py +++ b/tools/pynuttx/nxstub/target.py @@ -81,7 +81,7 @@ class Target: self.registers = registers or Registers(elf, arch=arch) self.memories = [] self.arch = arch - self.pid = 0 # Current thread PID + self.pid = self.PID0_ID # Current thread PID for mem in memories or []: # Go through the write process to merge overlapping memory regions @@ -176,6 +176,9 @@ class Target: self.registers = t.registers return self.registers + def current_thread(self) -> int: + return self.pid + def memory_read(self, address: int, length: int) -> bytes: self.logger.debug(f"Read: {address:#x} {length}Bytes") # Try cached memory -- Gitee From 5a46e4b930ab0d0a6ae00ae89a2a21ba02d191bc Mon Sep 17 00:00:00 2001 From: Xu Xingliang Date: Thu, 9 Jan 2025 09:33:58 +0800 Subject: [PATCH 063/235] nxstub: fix duplicated section/segments in elf/core VELAPLATFO-52029 Coredump may contain multiple memory regions for same address. Check the segments size against we want and continue to next segment until the size is enough for we read. Due to this, the `lief` may get confused when we call `elf.get_content_from_virtual_address`, so we now manually parsing all sections/segments. Change-Id: I68b3524f79ee5e5527c98d6a44d32ff7d29812fa Signed-off-by: Xu Xingliang --- tools/pynuttx/nxstub/utils.py | 37 +++++++++++++++++++++++------------ 1 file changed, 24 insertions(+), 13 deletions(-) diff --git a/tools/pynuttx/nxstub/utils.py b/tools/pynuttx/nxstub/utils.py index 84282d6da7c..830acee597e 100644 --- a/tools/pynuttx/nxstub/utils.py +++ b/tools/pynuttx/nxstub/utils.py @@ -62,28 +62,39 @@ def parse_elf(elf_file: str) -> lief.Binary: logging.error(f"Failed to parse ELF file: {elf_file}") return None - return elf.abstract + return elf def get_architecture(elf: lief.Binary): - return elf.header.architecture + return elf.abstract.header.architecture def get_endian(elf: lief.Binary) -> str: - return "l" if elf.header.endianness == lief.Header.ENDIANNESS.LITTLE else "b" + return ( + "l" if elf.abstract.header.endianness == lief.Header.ENDIANNESS.LITTLE else "b" + ) def read_from(elf: lief.Binary, addr, len=1) -> memoryview: - # For xtensa elf, read directly returns wrong value, manually parse the section in this case. - for section in elf.sections: if section.type == lief.ELF.Section.TYPE.PROGBITS: - if section.virtual_address <= addr < section.virtual_address + section.size: - off = addr - section.virtual_address + off = addr - section.virtual_address + if ( + section.virtual_address <= addr < section.virtual_address + section.size + and section.size - off >= len + ): return section.content[off : off + len] - if data := elf.get_content_from_virtual_address(addr, len): - return data + for segment in elf.segments: + if segment.type == lief.ELF.Segment.TYPE.LOAD: + off = addr - segment.virtual_address + if ( + segment.virtual_address + <= addr + < segment.virtual_address + segment.virtual_size + and segment.virtual_size - off >= len + ): + return segment.content[off : off + len] return None @@ -121,7 +132,7 @@ def read_string(elf: lief.Binary, addr): def get_inttype(elf: lief.Binary) -> Construct: endian = get_endian(elf) - bits = 64 if elf.header.is_64 else 32 + bits = 64 if elf.abstract.header.is_64 else 32 return { "32l": Int32sl, "32b": Int32sb, @@ -132,7 +143,7 @@ def get_inttype(elf: lief.Binary) -> Construct: def get_pointer_type(elf: lief.Binary) -> Construct: endian = get_endian(elf) - bits = 64 if elf.header.is_64 else 32 + bits = 64 if elf.abstract.header.is_64 else 32 return { "32l": Int32ul, "32b": Int32ub, @@ -142,7 +153,7 @@ def get_pointer_type(elf: lief.Binary) -> Construct: def get_pointer_size(elf: lief.Binary): - return 8 if elf.header.is_64 else 4 + return 8 if elf.abstract.header.is_64 else 4 def get_ncpus(elf: lief.Binary) -> int: @@ -186,7 +197,7 @@ def get_tcb_size(elf: lief.Binary) -> int: def get_reginfo(elf: lief.Binary) -> List[RegInfo]: - bits = 64 if elf.header.is_64 else 32 + bits = 64 if elf.abstract.header.is_64 else 32 # Now get register offset in TCB _, data = read_symbol(elf, "g_reg_offs") -- Gitee From 80b8ec78430ccdbd8331bca1c30c99dacda58ee4 Mon Sep 17 00:00:00 2001 From: xuxingliang Date: Mon, 13 Jan 2025 10:20:22 +0800 Subject: [PATCH 064/235] nxstub: add remap option to pass the real memory address VELAPLATFO-52029 The address access by foreign CPU may differ from this CPU. Use --remap from,to,length option to correct the real address for current CPU. E.g. --remap 0x21c00000,0x20000000,0xDFFA0 Change-Id: I84629727bc18545abd22e42391123a67f306b4d2 Signed-off-by: xuxingliang --- tools/pynuttx/nxstub/__init__.py | 14 +++++++++++++- tools/pynuttx/nxstub/target.py | 18 ++++++++++++++++-- 2 files changed, 29 insertions(+), 3 deletions(-) diff --git a/tools/pynuttx/nxstub/__init__.py b/tools/pynuttx/nxstub/__init__.py index c4b3bf572a9..9949f2e451f 100644 --- a/tools/pynuttx/nxstub/__init__.py +++ b/tools/pynuttx/nxstub/__init__.py @@ -135,11 +135,17 @@ def gdbstub_start(args): core = utils.parse_elf(args.core) if args.core else None + memremap = [] + if args.remap: + for remap in args.remap: + fromaddr, toaddr, length = map(lambda x: int(x, 16), remap.split(",")) + memremap.append((fromaddr, toaddr, length)) + if args.proxy is not None: print(f"Try proxying localhost:{args.proxy}...") target = TargetProxy(elf, args.arch, args.proxy) else: - target = Target(elf, args.arch, registers, memories, core) + target = Target(elf, args.arch, registers, memories, memremap, core) stub = GDBStub(target=target, port=args.port, proxymode=args.proxy is not None) @@ -211,6 +217,12 @@ def parse_args(args=None): type=str, help="The core dump file.", ) + parser.add_argument( + "--remap", + type=str, + nargs="*", + help="Remap the memory to another address, argument in format of 'from,to,length'.", + ) parser.add_argument( "-l", "--log", diff --git a/tools/pynuttx/nxstub/target.py b/tools/pynuttx/nxstub/target.py index c36a864f7c1..456cb9c85e7 100644 --- a/tools/pynuttx/nxstub/target.py +++ b/tools/pynuttx/nxstub/target.py @@ -66,14 +66,17 @@ class Target: arch=None, registers: Registers = None, memories: List[RawMemory] = None, + remap=None, core=None, ): """ The target that GDB stub operations on. :param elf: The ELF file path. + :param arch: The architecture of the target, e.g. "arm", "riscv", "mips", etc. :param registers: The optional initial register value, normally used for crash log analysis. :param memories: The optional initial memory regions, normally used for raw memory dump. - :param arch: The architecture of the target, e.g. "arm", "riscv", "mips", etc. + :param remap: The optional memory remap table, used to remap memory regions. A list of tuple (from, to, length). + :param core: The optional core dump file path. """ self.logger = logging.getLogger(__name__) self.elf = elf @@ -82,7 +85,7 @@ class Target: self.memories = [] self.arch = arch self.pid = self.PID0_ID # Current thread PID - + self.remap = remap or [] for mem in memories or []: # Go through the write process to merge overlapping memory regions self.memory_write(mem.address, mem.data) @@ -181,6 +184,17 @@ class Target: def memory_read(self, address: int, length: int) -> bytes: self.logger.debug(f"Read: {address:#x} {length}Bytes") + + # Check the real address from remap table + for fromaddr, toaddr, total in self.remap: + if toaddr <= address < toaddr + total: + address = fromaddr + (address - toaddr) + if address + length > fromaddr + total: + # Do not support cross region read + length = fromaddr + total - address + self.logger.debug(f"Remap to: {address:#x} {length}Bytes") + break + # Try cached memory for mem in self.memories: if mem.address <= address < mem.address + len(mem): -- Gitee From abad61fc7439f63f9a51705a181769ef69e86768 Mon Sep 17 00:00:00 2001 From: xuxingliang Date: Mon, 13 Jan 2025 10:28:31 +0800 Subject: [PATCH 065/235] nxgdb/stub: parse arguments firstly before starts stub process VELAPLATFO-52029 So the target stub --help will print the help message and exit directly. Change-Id: Ibce31a8e24beec25625f287856f04f7d03f7ca37 Signed-off-by: xuxingliang --- tools/pynuttx/nxgdb/target.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/tools/pynuttx/nxgdb/target.py b/tools/pynuttx/nxgdb/target.py index bb64d22ffee..29b92a665a3 100644 --- a/tools/pynuttx/nxgdb/target.py +++ b/tools/pynuttx/nxgdb/target.py @@ -42,6 +42,12 @@ class Target(gdb.Command): if "-a" not in args and "--arch" not in args: args += f" -a {gdb.selected_inferior().architecture().name().lower()}" + args = gdb.string_to_argv(args) + try: + parsed = nxstub.parse_args(args) + except SystemExit: + return + # If currently has connection to target, disconnect it inferior = gdb.selected_inferior() if inferior and inferior.connection and inferior.connection.is_valid(): @@ -61,7 +67,6 @@ class Target(gdb.Command): kill() - args = gdb.string_to_argv(args) process = multiprocessing.Process(target=nxstub.main, args=(args,)) process.start() self.process = process @@ -70,9 +75,4 @@ class Target(gdb.Command): print("") # Wait server to start - try: - parsed = nxstub.parse_args(args) - except SystemExit: - return - gdb.execute(f"target remote :{parsed.port}", from_tty=True) -- Gitee From 4abde7d6a7c9f359796eebc362170aa08796ab5b Mon Sep 17 00:00:00 2001 From: xuxingliang Date: Mon, 13 Jan 2025 14:05:39 +0800 Subject: [PATCH 066/235] nxstub: fetch registers from g_last_regs for running tasks VELAPLATFO-52029 Change-Id: If6c95a6876e0423bb5cbd616bb5cb5e2504504ed Signed-off-by: xuxingliang --- tools/pynuttx/nxstub/target.py | 26 ++++++++++++++++++++++---- 1 file changed, 22 insertions(+), 4 deletions(-) diff --git a/tools/pynuttx/nxstub/target.py b/tools/pynuttx/nxstub/target.py index 456cb9c85e7..ed734347eb2 100644 --- a/tools/pynuttx/nxstub/target.py +++ b/tools/pynuttx/nxstub/target.py @@ -133,21 +133,39 @@ class Target: self.logger.error(f"No threads info found: {g_npidhash}") return self.threads + ncpus = utils.get_ncpus(self.elf) + regsize = utils.get_regsize(self.elf) + + data, sym = self._read_symbol("g_running_tasks") # an array of pointers + g_running_tasks = utils.parse_array(data, pointer, ncpus) + self.logger.debug(f"g_running_tasks: {g_running_tasks}@{sym.value:#x}") + + data, _ = self._read_symbol("g_last_regs") # an array of uintptr_t + assert len(data) % regsize == 0 + g_last_regs = [data[i * regsize : (i + 1) * regsize] for i in range(ncpus)] + def parse_tcb(address: int) -> ThreadInfo: data = self.memory_read(address, tcbsize) if tcbinfo.name_off == 0: name = "" else: name = self._read_str(address + tcbinfo.name_off) - self.logger.debug(f"loading thread: {name}") + self.logger.debug(f"loading thread: {name}, tcb@{address:#x}") pid = utils.uint16_t(data[tcbinfo.pid_off : tcbinfo.pid_off + 2]) pid = pid if pid != 0 else self.PID0_ID state = utils.uint8_t(data[tcbinfo.state_off : tcbinfo.state_off + 1]) state = states[state] if state < len(states) else "Unknown" registers = Registers(self.elf, arch=self.arch) - xcpregs = data[tcbinfo.regs_off : tcbinfo.regs_off + pointer.sizeof()] - xcpregs = pointer.parse(xcpregs) - xcpregs = self.memory_read(xcpregs, utils.get_regsize(self.elf)) + + if address in g_running_tasks: + # Running task registers is not in memory, best chance is the registers + # stored in g_last_regs when assert happened. + xcpregs = g_last_regs[g_running_tasks.index(address)] + else: + off = tcbinfo.regs_off + xcpregs = data[off : off + pointer.sizeof()] + xcpregs = pointer.parse(xcpregs) + xcpregs = self.memory_read(xcpregs, regsize) registers.load(xcpregs=xcpregs) self.logger.debug(f"Parse TCB: {name}({pid},{state})") return ThreadInfo(name, pid, state, registers) -- Gitee From 8e6a84fd2219fa3e2e009e8315994f4b7ef804c9 Mon Sep 17 00:00:00 2001 From: xuxingliang Date: Mon, 13 Jan 2025 14:24:42 +0800 Subject: [PATCH 067/235] nxstub: PID of 0 and -1 means special thread in RSP VELAPLATFO-52029 Should keep current thread unchanged for PID of -1(all threads) and 0(current thread). Change-Id: Iaf2e48acbb9e119b64b44bf709eea2e269e88e26 Signed-off-by: xuxingliang --- tools/pynuttx/nxstub/target.py | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/tools/pynuttx/nxstub/target.py b/tools/pynuttx/nxstub/target.py index ed734347eb2..4535e7135d9 100644 --- a/tools/pynuttx/nxstub/target.py +++ b/tools/pynuttx/nxstub/target.py @@ -189,7 +189,14 @@ class Target: Return the registers for the thread """ self.logger.debug(f"Switch to thread {pid}") - pid = pid if pid is not None and pid > 0 else self.PID0_ID + if pid == -1 or pid == 0: + # -1: all threads, 0: current thread. No need to switch for both cases + # See https://sourceware.org/gdb/current/onlinedocs/gdb.html/Packets.html#Packets + return self.registers + + if pid is None: + # None is only used during our initial setup, not of GDB RSP protocol + pid = self.PID0_ID for t in self.threads: if pid == t.pid: -- Gitee From 3967e29f0cdd7f983cea83b2fa7d66d728d3b1ed Mon Sep 17 00:00:00 2001 From: xuxingliang Date: Mon, 13 Jan 2025 18:10:53 +0800 Subject: [PATCH 068/235] nxstub/registers add xt-gdb support VELAPLATFO-52177 Though esp32s3-gdb can work most of the time for xtensa arch, two main issues have been met: 1. Some disassembly returns wrong code, such as spliting one command to two. 2. When there's memory corruption, info threads may cause GDB assert and exit directly. Due to this, we add xt-gdb back, and keep -a argument same as original gdbserver.py Change-Id: I2ac5fc6842f0e28992ecfbed5c1f8852d85973e8 Signed-off-by: xuxingliang --- tools/pynuttx/nxstub/registers.py | 28 +++++++++++++++++++++++++++- 1 file changed, 27 insertions(+), 1 deletion(-) diff --git a/tools/pynuttx/nxstub/registers.py b/tools/pynuttx/nxstub/registers.py index 72bb900ec9e..ec982f8e767 100644 --- a/tools/pynuttx/nxstub/registers.py +++ b/tools/pynuttx/nxstub/registers.py @@ -190,7 +190,7 @@ g_reg_table = { ("fs", 22, 0), ], }, - "xtensa": { + "esp32s3": { "architecture": "xtensa", # Use xtensa-esp32s3-elf-gdb "feature": "", "registers": [ @@ -216,6 +216,32 @@ g_reg_table = { ("windowstart", 70, 280, 1), ], }, + "xtensa": { + "architecture": "xtensa", # Use xt-gdb + "feature": "", + "registers": [ + ("pc", 32, 0), + ("ps", 742, 472, 0x40000), + ("a0", 256, 4), + ("a1", 257, 0), + ("a2", 258, 0), + ("a3", 259, 0), + ("a4", 260, 0), + ("a5", 261, 0), + ("a6", 262, 0), + ("a7", 263, 0), + ("a8", 264, 0), + ("a9", 265, 0), + ("a10", 266, 0), + ("a11", 267, 0), + ("a12", 268, 0), + ("a13", 269, 0), + ("a14", 270, 0), + ("a15", 271, 0), + ("windowbase", 584, 308, 0), + ("windowstart", 585, 312, 1), + ], + }, } -- Gitee From 4979a63d166a55cd9f878f3eac5b442170586d50 Mon Sep 17 00:00:00 2001 From: xuxingliang Date: Mon, 13 Jan 2025 19:26:11 +0800 Subject: [PATCH 069/235] nxstub: add monitor command setregs VELAPLATFO-52177 Add monitor command to load register from specified address or symbol. Do note that expression is not supported as argument, compared to nxgdb/thread.py setregs command. This is useful for xt-gdb that cannot load GDB plugin. E.g. (xt-gdb) p g_pidhash[1].xcp = {saved_regs = 0x0, regs = 0x1bcfd178} (xt-gdb) monitor setregs 0x1bcfd178 Loaded registers from 0x1bcfd178 (xt-gdb) monitor setregs g_last_regs Loaded registers from 0x1bc012f0 Change-Id: I92211ed7a6df78e0d73e3a806ef9cea6cea6e9f9 Signed-off-by: xuxingliang --- tools/pynuttx/nxstub/gdbstub.py | 17 +++++++++++++++++ tools/pynuttx/nxstub/target.py | 27 ++++++++++++++++++++++++++- 2 files changed, 43 insertions(+), 1 deletion(-) diff --git a/tools/pynuttx/nxstub/gdbstub.py b/tools/pynuttx/nxstub/gdbstub.py index 27a702d9233..976571e35bf 100644 --- a/tools/pynuttx/nxstub/gdbstub.py +++ b/tools/pynuttx/nxstub/gdbstub.py @@ -115,6 +115,7 @@ class GDBStub: self.send_packet("") def process_packet(self, packet: bytes): + self.logger.debug(f"Process packet: {packet}") attribute = "handle_" + chr(packet[0]) handler = { "handle_?": self.handle_questionmark, @@ -175,6 +176,22 @@ class GDBStub: info = next((t for t in self.threads if t.pid == pid), None) info = f"{info.name},{info.state}" if info else f"Invalid PID {pid}" self.send_packet(hexlify(info.encode("ascii"))) + elif packet.startswith("qRcmd"): + try: + _, command = packet.split(",") + command = unhexlify(command) + response = self.target.monitor_command(command) + if response is None: + self.send_unsupported() + return + except Exception as e: + self.logger.error(f"Error executing monitor command: {e}") + # Note that older GDB may treat it as normal output instead of error, but nothing hurts. + response = f"E.{e}\n" + + if isinstance(response, str): + response = response.encode("ascii") + self.send_packet(hexlify(response)) else: self.send_unsupported() diff --git a/tools/pynuttx/nxstub/target.py b/tools/pynuttx/nxstub/target.py index 4535e7135d9..124f2fa993f 100644 --- a/tools/pynuttx/nxstub/target.py +++ b/tools/pynuttx/nxstub/target.py @@ -82,7 +82,7 @@ class Target: self.elf = elf self.core = core self.registers = registers or Registers(elf, arch=arch) - self.memories = [] + self.memories: List[RawMemory] = [] self.arch = arch self.pid = self.PID0_ID # Current thread PID self.remap = remap or [] @@ -272,3 +272,28 @@ class Target: memories.remove(m2) m.data += m2.data[end - m2.address :] + + def monitor_command(self, command: bytes) -> str: + """Handle monitor command""" + self.logger.debug(f"Monitor command: {command}") + if command.startswith(b"setregs"): + command = command.decode("ascii") + _, address = command.split(" ") + try: + address = ( + int(address, 16) + if "0x" in address or "0X" in address + else int(address) + ) + except ValueError: + # try if it's a symbol, note that expression is not supported. + address = utils.get_symbol(self.elf, address).value + + self.registers.load(self.memory_read(address, utils.get_regsize(self.elf))) + return f"Loaded registers from {address:#x}\n" + elif command.startswith(b"help"): + return ( + "setregs : Load registers from address or symbol.\n" + "\tNeed to execute `maint flush register-cache` to see latest registers\n" + "help: Show this help message\n" + ) -- Gitee From 2b49d332c46aa47cb81789a6787efb01b6801190 Mon Sep 17 00:00:00 2001 From: xuxingliang Date: Tue, 14 Jan 2025 11:35:45 +0800 Subject: [PATCH 070/235] nxstub: imporve immunity to mm corruption VELAPLATFO-52177 The TCB could be corrupted, continue to parse next tcb instead exit directly. Change-Id: Id7a7e67102387474ab36bd3b1296d7d0961abaeb Signed-off-by: xuxingliang --- tools/pynuttx/nxstub/target.py | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/tools/pynuttx/nxstub/target.py b/tools/pynuttx/nxstub/target.py index 124f2fa993f..786c1f334eb 100644 --- a/tools/pynuttx/nxstub/target.py +++ b/tools/pynuttx/nxstub/target.py @@ -145,7 +145,12 @@ class Target: g_last_regs = [data[i * regsize : (i + 1) * regsize] for i in range(ncpus)] def parse_tcb(address: int) -> ThreadInfo: + registers = Registers(self.elf, arch=self.arch) data = self.memory_read(address, tcbsize) + if not data or len(data) != tcbsize: + self.logger.error(f"Invalid TCB size: {len(data)} != {tcbsize}") + return ThreadInfo("", 0, "Invalid", registers) + if tcbinfo.name_off == 0: name = "" else: @@ -155,7 +160,6 @@ class Target: pid = pid if pid != 0 else self.PID0_ID state = utils.uint8_t(data[tcbinfo.state_off : tcbinfo.state_off + 1]) state = states[state] if state < len(states) else "Unknown" - registers = Registers(self.elf, arch=self.arch) if address in g_running_tasks: # Running task registers is not in memory, best chance is the registers @@ -166,7 +170,12 @@ class Target: xcpregs = data[off : off + pointer.sizeof()] xcpregs = pointer.parse(xcpregs) xcpregs = self.memory_read(xcpregs, regsize) - registers.load(xcpregs=xcpregs) + + try: + registers.load(xcpregs=xcpregs) + except ValueError as e: + self.logger.error(f"Failed to load registers: {e}") + self.logger.debug(f"Parse TCB: {name}({pid},{state})") return ThreadInfo(name, pid, state, registers) -- Gitee From 08bb0d8d0e75dd2a0eab1f368bb97aa65a1250da Mon Sep 17 00:00:00 2001 From: Bowen Wang Date: Thu, 9 Jan 2025 00:39:38 +0800 Subject: [PATCH 071/235] nxgdb/rpmsg.py: support dump the rpmsg virtio transport VELAPLATFO-51875 Now we can dump the rpmsg virtio transport virtqueue. If only need dump the transport, use: (gdb) rpmsgdump -t Rpmsg Device: rpmsg:0x184dbeb8 rdev:0x184dbf34 Rpmsg Virtio Trasport: rvdev:0x184dbf34 h2r_buf_size:512 r2h_buf_size:512 Rpmsg Virtqueues: vq name size free queued desc_head_idx available_idx avail.idx avail.flags used_cons_idx used.idx used.flags -- ---- ---- ---- ------ ------------- ------------- --------- ----------- ------------- -------- ---------- 0x18598da0 tx_vq 8 1 0 7 0 2233 0 2226 2233 0 0x18598e30 rx_vq 8 0 0 32768 0 1704 0 1696 1696 0 Change-Id: If291ec7511ce4fdae2f940e365fba587a35b859b Signed-off-by: Bowen Wang --- tools/pynuttx/nxgdb/rpmsg.py | 97 +++++++++++++++++++++++++++++++++--- 1 file changed, 89 insertions(+), 8 deletions(-) diff --git a/tools/pynuttx/nxgdb/rpmsg.py b/tools/pynuttx/nxgdb/rpmsg.py index a00e2249351..d3ec0b3b63f 100644 --- a/tools/pynuttx/nxgdb/rpmsg.py +++ b/tools/pynuttx/nxgdb/rpmsg.py @@ -20,6 +20,8 @@ # ############################################################################ +import argparse + import gdb from . import utils @@ -39,14 +41,89 @@ class RPMsgDump(gdb.Command): "ns_bound_cb", "ns_unbind_cb", ] + VQ_HEADER = [ + "vq", + "name", + "size", + "free", + "queued", + "desc_head_idx", + "available_idx", + "avail.idx", + "avail.flags", + "used_cons_idx", + "used.idx", + "used.flags", + ] CALLBACK_FORAMTTER = "{:<20} {:<40} {:<40}" ENDPOINT_FORMATTER = "{:<20} {:<20} {:<12} {:<12} {:<40} {:<40} {:<40}" + VQ_FORMATTER = ( + "{:<12} {:<8} {:<5} {:<5} {:<7} {:<14} {:<14} {:<10} {:<12} {:<14} {:<9} {:<11}" + ) def __init__(self): if utils.get_symbol_value("CONFIG_RPMSG"): super(RPMsgDump, self).__init__("rpmsgdump", gdb.COMMAND_USER) + def parse_args(self, arg): + parser = argparse.ArgumentParser(description=self.__doc__) + parser.add_argument( + "-t", + "--transport-only", + action="store_true", + help="Only dump the rpmsg transport layer", + ) + + try: + return parser.parse_args(gdb.string_to_argv(arg)) + except SystemExit: + return + + def dump_virtqueue(self, vq): + vr = vq["vq_ring"] + gdb.write( + self.VQ_FORMATTER.format( + f"{vq}", + f"{vq['vq_name'].string()}", + f"{vq['vq_nentries']}", + f"{vq['vq_free_cnt']}", + f"{vq['vq_queued_cnt']}", + f"{vq['vq_desc_head_idx']}", + f"{vq['vq_available_idx']}", + f"{vr['avail']['idx']}", + f"{vr['avail']['flags']}", + f"{vq['vq_used_cons_idx']}", + f"{vr['used']['idx']}", + f"{vr['used']['flags']}", + ) + + "\n" + ) + + def dump_rpmsg_virtio(self, rdev): + real_addr = hex( + gdb.lookup_symbol("rpmsg_virtio_get_tx_payload_buffer")[0].value().address + ) + ops_addr = hex(int(utils.Value(rdev["ops"]["get_tx_payload_buffer"])) & ~1) + if real_addr != ops_addr: + return + + rvdev = rdev.cast(utils.lookup_type("struct rpmsg_virtio_device").pointer()) + + gdb.write( + f"Rpmsg Virtio Trasport: rvdev:{rvdev} h2r_buf_size:{rvdev['config']['h2r_buf_size']}" + f"r2h_buf_size:{rvdev['config']['r2h_buf_size']}\n" + ) + for vbuff in NxList(rvdev["reclaimer"], "struct vbuff_reclaimer_t", "node"): + gdb.write(f"rvdev reclaimer vbuff:{vbuff} idx:{vbuff['idx']}") + + gdb.write("Rpmsg Virtqueues:\n") + self.print_headers(self.VQ_HEADER, self.VQ_FORMATTER) + self.dump_virtqueue(rvdev["svq"]) + self.dump_virtqueue(rvdev["rvq"]) + + gdb.write("\n") + def print_headers(self, headers, formatter): gdb.write(formatter.format(*headers) + "\n") gdb.write(formatter.format(*["-" * len(header) for header in headers]) + "\n") @@ -79,13 +156,11 @@ class RPMsgDump(gdb.Command): ) def dump_rdev(self, rdev): - gdb.write(f"device:{rdev}\n") - self.dump_rdev_bitmap(rdev) self.dump_rdev_epts(rdev["endpoints"]) def dump_rpmsg_cb(self): - gdb.write("g_rpmsg_cb:\n") + gdb.write("Rpmsg Callback:\n") self.print_headers(self.CALLBACK_HEADER, self.CALLBACK_FORAMTTER) output = [] @@ -97,11 +172,17 @@ class RPMsgDump(gdb.Command): ) gdb.write("\n".join(output) + "\n") - def dump_rpmsg(self): - gdb.write("g_rpmsg:\n") + def dump_rpmsg(self, transport): for rpmsg in NxList(gdb.parse_and_eval("g_rpmsg"), "struct rpmsg_s", "node"): - self.dump_rdev(rpmsg["rdev"]) + gdb.write(f"Rpmsg Device: rpmsg:{rpmsg} rdev:{rpmsg['rdev']}\n") + if not transport: + self.dump_rdev(rpmsg["rdev"]) + self.dump_rpmsg_virtio(rpmsg["rdev"]) def invoke(self, args, from_tty): - self.dump_rpmsg_cb() - self.dump_rpmsg() + if not (args := self.parse_args(args)): + return + + if not args.transport: + self.dump_rpmsg_cb() + self.dump_rpmsg(args.transport) -- Gitee From f7d42c6e3e5b7ee8d831a1c5450340904bcf682d Mon Sep 17 00:00:00 2001 From: yangao1 Date: Mon, 13 Jan 2025 21:10:40 +0800 Subject: [PATCH 072/235] nxgdb/dmesg.py:add use gdb dump rpmsg_syslog VELAPLATFO-52183 (gdb) dmesg RAM log: [01/06 02:27:05] [ 1] [cp] reset mode:1 ... [01/06 02:27:05] [ 1] [cp] Dump board_reset backtrace: [01/06 02:27:05] [ 1] [cp] sched_dumpstack: backtrace| 1: 0x10a0d880 0x10a0a78e 0x10a0d8b6 0x10a0f29e 0x10a0f182 [01/06 02:27:05] [ 1] [cp] Time: Mon Jan 6 02:27:05 2025 ---END of RAMLOG RPMSG syslog: dumpstack: backtrace|10: 0x10a0d880 0x10a0a78e 0x10a110de 0x10a3a482 0x10a3c4fa 0x10a23358 0x10a4aaee 0x10a34a7c [01/06 02:27:05] [ 1] [cp] sched_dumpstack: backtrace|10: 0x10a2330a 0x10a0f1f4 [01/06 02:27:05] [ 1] [cp] sched_dumpstack: backtrace|11: 0x10a0d880 0x10a0a78e 0x10a110de 0x10a3a482 0x10a15152 0x10a0f182 [01/06 02:27:05] [ 1] [cp] sched_dumpstack: backtrace|15: 0x10a0d880 0x10a0a78e 0x10a0d8b6 0x10a174d0 0x10a3a482 0x10a3c4fa 0x10a222ee 0x10a18c66 [01/06 02:27:05] [ 1] [cp] Time: Mon Jan 6 02:27:05 2025 ---END of RPMSG SYSLOG--- Change-Id: I89df30bb241f845231b7b5a24ad23380e45a73a1 Signed-off-by: yangao1 --- tools/pynuttx/nxgdb/dmesg.py | 35 ++++++++++++++++++++++++----------- 1 file changed, 24 insertions(+), 11 deletions(-) diff --git a/tools/pynuttx/nxgdb/dmesg.py b/tools/pynuttx/nxgdb/dmesg.py index 8f4a487c5f9..c4c8b028091 100644 --- a/tools/pynuttx/nxgdb/dmesg.py +++ b/tools/pynuttx/nxgdb/dmesg.py @@ -25,18 +25,17 @@ import gdb from . import utils CONFIG_RAMLOG_SYSLOG = utils.get_symbol_value("CONFIG_RAMLOG_SYSLOG") +CONFIG_SYSLOG_RPMSG = utils.get_symbol_value("CONFIG_SYSLOG_RPMSG") class Dmesg(gdb.Command): def __init__(self): - if CONFIG_RAMLOG_SYSLOG: + if CONFIG_RAMLOG_SYSLOG or CONFIG_SYSLOG_RPMSG: super().__init__("dmesg", gdb.COMMAND_USER) - def _get_buf(self): - sysdev = utils.gdb_eval_or_none("g_sysdev") - if not sysdev: - gdb.write("RAM log not available.\n") - return None + def _get_ramlog(self): + if not (sysdev := utils.gdb_eval_or_none("g_sysdev")): + return "RAM log not available" rl_header = sysdev["rl_header"] rl_bufsize = sysdev["rl_bufsize"] @@ -55,17 +54,31 @@ class Dmesg(gdb.Command): return buf.decode("utf-8", errors="replace") + def _get_rpmsg_syslog(self): + if not (priv := utils.gdb_eval_or_none("g_syslog_rpmsg")): + return "RPMsg syslog not avaliable" + + buffer = bytes(gdb.selected_inferior().read_memory(priv.buffer, priv.size)) + buf = buffer.replace(b"\0", "␀".encode("utf-8")) + return buf.decode("utf-8", errors="replace") + def diagnose(self, *args, **kwargs): - buf = self._get_buf() + ramlog = self._get_ramlog() + rpmsg_syslog = self._get_rpmsg_syslog() + return { - "title": "RAM log", + "title": "RAM log and RPMsg Syslog", "summary": ( - f"Buffer length:{len(buf)} bytes" if buf else "Buffer not available" + f"RAM log length: {len(ramlog)} bytes. RPMSG log length:{len(rpmsg_syslog)} bytes." ), "result": "info", "command": "dmesg", - "message": buf, + "message": f"RAM log:\n{ramlog}\n RPMSG syslog:{rpmsg_syslog}", } def invoke(self, args, from_tty): - gdb.write(f"{self._get_buf()}\n") + ramlog = self._get_ramlog() + rpmsg_syslog = self._get_rpmsg_syslog() + + print(f"RAM log:{ramlog}\n---END of RAMLOG") + print(f"RPMSG syslog:{rpmsg_syslog}\n---END of RPMSG SYSLOG---") -- Gitee From 7914d9b7cb1c1266b18246c1208f922e1298b2ff Mon Sep 17 00:00:00 2001 From: buxiasen Date: Thu, 16 Jan 2025 19:11:54 +0800 Subject: [PATCH 073/235] tool/pynuttx: fix pid ignored when MM_BACKTRACE 0 VELAPLATFO-51555 Change-Id: Ib39732b56d5655e5382f0f02c9941df6ec540e9e Signed-off-by: buxiasen --- tools/pynuttx/nxgdb/mm.py | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/tools/pynuttx/nxgdb/mm.py b/tools/pynuttx/nxgdb/mm.py index 9a0a7afc508..4d47065cae8 100644 --- a/tools/pynuttx/nxgdb/mm.py +++ b/tools/pynuttx/nxgdb/mm.py @@ -42,6 +42,7 @@ if "backtrace" in utils.get_fieldnames(mm_freenode_s): else: CONFIG_MM_BACKTRACE = -1 +CONFIG_MM_BACKTRACE_PID = "pid" in utils.get_fieldnames(mm_freenode_s) CONFIG_MM_BACKTRACE_SEQNO = "seqno" in utils.get_fieldnames(mm_freenode_s) PID_MM_INVALID = -100 @@ -115,14 +116,16 @@ class MemPoolBlock: @property def seqno(self) -> int: if not self._seqno: - self._seqno = int(self.blk["seqno"]) if CONFIG_MM_BACKTRACE_SEQNO else -100 + self._seqno = ( + int(self.blk["seqno"]) if CONFIG_MM_BACKTRACE_SEQNO else PID_MM_INVALID + ) return self._seqno @property def pid(self) -> int: if not self._pid: self._pid = ( - int(self.blk["pid"]) if CONFIG_MM_BACKTRACE >= 0 else PID_MM_INVALID + int(self.blk["pid"]) if CONFIG_MM_BACKTRACE_PID else PID_MM_INVALID ) return self._pid @@ -460,8 +463,7 @@ class MMNode(gdb.Value, p.MMFreeNode): @property def pid(self) -> int: - # Only available when CONFIG_MM_BACKTRACE >= 0 - if CONFIG_MM_BACKTRACE >= 0: + if CONFIG_MM_BACKTRACE_PID: return int(self["pid"]) return PID_MM_INVALID -- Gitee From 47ee3f324e51638d8131c8ebea9a14f9adf2bae7 Mon Sep 17 00:00:00 2001 From: xuxingliang Date: Wed, 15 Jan 2025 12:06:48 +0800 Subject: [PATCH 074/235] nxgdb/mm: fix parsing macro MM_MIN_CHUNK VELAPLATFO-52290 MM_MIN_CHUNK is a complex macro, if GDB failed to parse it, our fallback solution will also fail because it cannot process macro that contains macro. Use the math to match code behavior. Change-Id: I936e902c4296518086d2a1136fb6ffe1222b2b45 Signed-off-by: xuxingliang --- tools/pynuttx/nxgdb/mm.py | 3 ++- tools/pynuttx/nxgdb/utils.py | 9 +++++++++ 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/tools/pynuttx/nxgdb/mm.py b/tools/pynuttx/nxgdb/mm.py index 4d47065cae8..e548ad9b700 100644 --- a/tools/pynuttx/nxgdb/mm.py +++ b/tools/pynuttx/nxgdb/mm.py @@ -384,7 +384,8 @@ class MMNode(gdb.Value, p.MMFreeNode): MM_MASK_BIT = MM_ALLOC_BIT | MM_PREVFREE_BIT MM_SIZEOF_ALLOCNODE = utils.sizeof("struct mm_allocnode_s") MM_ALLOCNODE_OVERHEAD = MM_SIZEOF_ALLOCNODE - utils.sizeof("mmsize_t") - MM_MIN_CHUNK = utils.get_symbol_value("MM_MIN_CHUNK", locspec="mm_initialize") + MM_MIN_SHIFT = utils.log2ceil(utils.sizeof("struct mm_freenode_s")) + MM_MIN_CHUNK = 1 << MM_MIN_SHIFT def __init__(self, node: gdb.Value): if node.type.code == gdb.TYPE_CODE_PTR: diff --git a/tools/pynuttx/nxgdb/utils.py b/tools/pynuttx/nxgdb/utils.py index 390196af90e..cfdd41eb1b9 100644 --- a/tools/pynuttx/nxgdb/utils.py +++ b/tools/pynuttx/nxgdb/utils.py @@ -26,6 +26,7 @@ import argparse import hashlib import importlib import json +import math import os import re import shlex @@ -548,6 +549,14 @@ def sizeof(t: Union[str, gdb.Type]): return t.sizeof +def log2ceil(n): + return int(math.ceil(math.log2(n))) + + +def log2floor(n): + return int(math.floor(math.log2(n))) + + # Machine Specific Helper Functions -- Gitee From 7ef7d88a2dc46f68150dd6b19543dd7479663266 Mon Sep 17 00:00:00 2001 From: xuxingliang Date: Tue, 14 Jan 2025 22:26:26 +0800 Subject: [PATCH 075/235] nxgdb/fs: fix exception when failed to parse symbol VELAPLATFO-52290 1. Parse struct fields to determine array length. 2. Add default value if the macro failed to parse. Change-Id: Ia230c2e6022adba75ed2a6bdd08c5c4df122583e Signed-off-by: xuxingliang --- tools/pynuttx/nxgdb/fs.py | 17 +++++++--- tools/pynuttx/nxgdb/mm.py | 11 +++---- tools/pynuttx/nxgdb/utils.py | 60 ++++++++++++++++++++++++------------ 3 files changed, 57 insertions(+), 31 deletions(-) diff --git a/tools/pynuttx/nxgdb/fs.py b/tools/pynuttx/nxgdb/fs.py index 79e71ccf156..18514e2acd1 100644 --- a/tools/pynuttx/nxgdb/fs.py +++ b/tools/pynuttx/nxgdb/fs.py @@ -30,17 +30,24 @@ from . import utils from .protocols import fs as p from .protocols.thread import Tcb -FSNODEFLAG_TYPE_MASK = utils.get_symbol_value("FSNODEFLAG_TYPE_MASK") +FSNODEFLAG_TYPE_MASK = 0x0000000F CONFIG_PSEUDOFS_FILE = utils.get_symbol_value("CONFIG_PSEUDOFS_FILE") CONFIG_PSEUDOFS_ATTRIBUTES = utils.get_symbol_value("CONFIG_PSEUDOFS_ATTRIBUTES") -CONFIG_FS_BACKTRACE = utils.get_symbol_value("CONFIG_FS_BACKTRACE") -CONFIG_NFILE_DESCRIPTORS_PER_BLOCK = int( - utils.get_symbol_value("CONFIG_NFILE_DESCRIPTORS_PER_BLOCK") -) +CONFIG_FS_BACKTRACE = utils.get_field_nitems("struct file", "f_backtrace") CONFIG_FS_SHMFS = utils.get_symbol_value("CONFIG_FS_SHMFS") +CONFIG_NFILE_DESCRIPTORS_PER_BLOCK = utils.get_field_nitems( + "struct filelist", "fl_prefiles" +) + +if CONFIG_NFILE_DESCRIPTORS_PER_BLOCK is None: + # For some branches, this field does not exist + CONFIG_NFILE_DESCRIPTORS_PER_BLOCK = ( + utils.gdb_eval_or_none("CONFIG_NFILE_DESCRIPTORS_PER_BLOCK") or 8 + ) + g_special_inodes = {} # Map of the special inodes including epoll, inotify, etc. diff --git a/tools/pynuttx/nxgdb/mm.py b/tools/pynuttx/nxgdb/mm.py index e548ad9b700..17457ec6a9a 100644 --- a/tools/pynuttx/nxgdb/mm.py +++ b/tools/pynuttx/nxgdb/mm.py @@ -35,15 +35,12 @@ from .utils import Value # of utils.get_symbol_value("CONFIG_MM_BACKTRACE") because the latter may report # wrong value on some platforms. -mm_freenode_s = utils.lookup_type("struct mm_freenode_s") - -if "backtrace" in utils.get_fieldnames(mm_freenode_s): - CONFIG_MM_BACKTRACE = utils.nitems(mm_freenode_s["backtrace"]) -else: +CONFIG_MM_BACKTRACE = utils.get_field_nitems("struct mm_freenode_s", "backtrace") +if CONFIG_MM_BACKTRACE is None: CONFIG_MM_BACKTRACE = -1 -CONFIG_MM_BACKTRACE_PID = "pid" in utils.get_fieldnames(mm_freenode_s) -CONFIG_MM_BACKTRACE_SEQNO = "seqno" in utils.get_fieldnames(mm_freenode_s) +CONFIG_MM_BACKTRACE_PID = utils.has_field("struct mm_freenode_s", "pid") +CONFIG_MM_BACKTRACE_SEQNO = utils.has_field("struct mm_freenode_s", "seqno") PID_MM_INVALID = -100 PID_MM_MEMPOOL = -1 diff --git a/tools/pynuttx/nxgdb/utils.py b/tools/pynuttx/nxgdb/utils.py index cfdd41eb1b9..692ffaca835 100644 --- a/tools/pynuttx/nxgdb/utils.py +++ b/tools/pynuttx/nxgdb/utils.py @@ -35,6 +35,7 @@ from typing import List, Optional, Tuple, Union import gdb from nxelf.macros import fetch_macro_info, try_expand +from typing_extensions import TypeAlias from .protocols.thread import Tcb @@ -42,6 +43,7 @@ g_symbol_cache = {} g_type_cache = {} g_macro_ctx = None g_backtrace_cache = {} +TypeOrStr: TypeAlias = Union[gdb.Type, str] class Value(gdb.Value): @@ -241,7 +243,7 @@ def lookup_type(name, block=None) -> gdb.Type: return g_type_cache[key] -def get_fieldnames(t: gdb.Type) -> List[str]: +def get_fieldnames(t: TypeOrStr) -> List[str]: """Return the field names of a type""" if isinstance(t, str): t = lookup_type(t) @@ -249,6 +251,34 @@ def get_fieldnames(t: gdb.Type) -> List[str]: return [f.name for f in t.fields()] +def get_type_field(obj: Union[TypeOrStr, gdb.Value], field: str) -> gdb.Field: + """ + Get the type field descriptor from a type or string, or value object. + """ + + if isinstance(obj, str): + t = lookup_type(obj) + elif isinstance(obj, gdb.Type): + t = obj + elif isinstance(obj, gdb.Value): + t = obj.type + else: + raise gdb.GdbError(f"Unsupported type {type(obj)}") + + while t.code in (gdb.TYPE_CODE_PTR, gdb.TYPE_CODE_ARRAY, gdb.TYPE_CODE_TYPEDEF): + t = t.target() + + for f in t.fields(): + if f.name == field: + return f + + +def get_field_nitems(t: TypeOrStr, field: str) -> Union[int, None]: + """Return the array length of a field in type, or None if no such field""" + if field := get_type_field(t, field): + return nitems(field) + + long_type = lookup_type("long") # Common Helper Functions @@ -260,7 +290,7 @@ def get_long_type(): return long_type -def offset_of(typeobj: Union[gdb.Type, str], field: str) -> Union[int, None]: +def offset_of(typeobj: TypeOrStr, field: str) -> Union[int, None]: """Return the offset of a field in a structure""" if type(typeobj) is str: typeobj = gdb.lookup_type(typeobj) @@ -278,7 +308,7 @@ def offset_of(typeobj: Union[gdb.Type, str], field: str) -> Union[int, None]: def container_of( - ptr: Union[gdb.Value, int], typeobj: Union[gdb.Type, str], member: str + ptr: Union[gdb.Value, int], typeobj: TypeOrStr, member: str ) -> gdb.Value: """ Return a pointer to the containing data structure. @@ -445,26 +475,18 @@ def get_symbol_value(name, locspec="nx_start", cacheable=True): return value -def get_field(val, key, default=None): - """Get a field from a gdb.Value, return default if key not found""" +def get_field(obj: gdb.Value, field: Union[str, gdb.Field], default=None) -> gdb.Value: + """ + Get a field value from a gdb.Value, return default if field is not found. + """ try: - return val[key] if val else default + return obj[field] if obj else default except gdb.error: return default -def has_field(obj: Union[gdb.Type, gdb.Value], key): - if isinstance(obj, gdb.Type): - t = obj - elif isinstance(obj, gdb.Value): - t = obj.type - else: - raise gdb.GdbError(f"Unsupported type {type(obj)}") - - while t.code in (gdb.TYPE_CODE_PTR, gdb.TYPE_CODE_ARRAY, gdb.TYPE_CODE_TYPEDEF): - t = t.target() - - return any(f.name == key for f in t.fields()) +def has_field(obj: Union[TypeOrStr, gdb.Value], field): + return get_type_field(obj, field) is not None def get_bytes(val, size): @@ -534,7 +556,7 @@ def alias(name, command): pass -def nitems(array): +def nitems(array: Union[gdb.Field, gdb.Type]) -> int: array_type = array.type element_type = array_type.target() element_size = element_type.sizeof -- Gitee From 00974c924f4ace11e9e7bbbef1b8c5cea71a82f2 Mon Sep 17 00:00:00 2001 From: buxiasen Date: Sat, 18 Jan 2025 15:03:30 +0800 Subject: [PATCH 076/235] nxgdb/mm: fix pool backtrace_pid error VELAPLATFO-51555 Reduce use of get_symbol_value CONFIG_MM_BACKTRACE. Change-Id: Iaf36bb77f3841ce44aaef35b1b74a349fe9ddfae Signed-off-by: buxiasen --- tools/pynuttx/nxgdb/mm.py | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/tools/pynuttx/nxgdb/mm.py b/tools/pynuttx/nxgdb/mm.py index 17457ec6a9a..a4eb5497877 100644 --- a/tools/pynuttx/nxgdb/mm.py +++ b/tools/pynuttx/nxgdb/mm.py @@ -36,12 +36,16 @@ from .utils import Value # wrong value on some platforms. CONFIG_MM_BACKTRACE = utils.get_field_nitems("struct mm_freenode_s", "backtrace") -if CONFIG_MM_BACKTRACE is None: - CONFIG_MM_BACKTRACE = -1 - CONFIG_MM_BACKTRACE_PID = utils.has_field("struct mm_freenode_s", "pid") CONFIG_MM_BACKTRACE_SEQNO = utils.has_field("struct mm_freenode_s", "seqno") +if CONFIG_MM_BACKTRACE is None: + # For backward compatibility, use 0 to indicate backtrace is disabled + # but pid, seqno is used + CONFIG_MM_BACKTRACE = ( + 0 if CONFIG_MM_BACKTRACE_PID or CONFIG_MM_BACKTRACE_SEQNO else -1 + ) + PID_MM_INVALID = -100 PID_MM_MEMPOOL = -1 @@ -211,8 +215,7 @@ class MemPool(Value, p.MemPool): """Real block size including backtrace overhead""" if not self._blksize: blksize = self["blocksize"] - backtrace = utils.get_symbol_value("CONFIG_MM_BACKTRACE") - if CONFIG_MM_BACKTRACE is not None and backtrace >= 0: + if CONFIG_MM_BACKTRACE >= 0: mempool_backtrace_s = utils.lookup_type("struct mempool_backtrace_s") size_t = utils.lookup_type("size_t") align = ( -- Gitee From 229194d0ed913158639c2bfde479d921f8f7aefb Mon Sep 17 00:00:00 2001 From: xuxingliang Date: Tue, 21 Jan 2025 10:29:35 +0800 Subject: [PATCH 077/235] nxgdb/fs: fix failed to format gdb.Value VELAPLATFO-52621 On trunk branch, need patch https://gerrit.pt.mioffice.cn/c/vela/nuttx/+/4891676 to get the macro value CONFIG_NFILE_DESCRIPTORS_PER_BLOCK reliably. Change-Id: Ibd17ee2f61e7eedb888cc27c449ab35055ecdc27 Signed-off-by: xuxingliang --- tools/pynuttx/nxgdb/fs.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/pynuttx/nxgdb/fs.py b/tools/pynuttx/nxgdb/fs.py index 18514e2acd1..a0382c1ac99 100644 --- a/tools/pynuttx/nxgdb/fs.py +++ b/tools/pynuttx/nxgdb/fs.py @@ -45,7 +45,7 @@ CONFIG_NFILE_DESCRIPTORS_PER_BLOCK = utils.get_field_nitems( if CONFIG_NFILE_DESCRIPTORS_PER_BLOCK is None: # For some branches, this field does not exist CONFIG_NFILE_DESCRIPTORS_PER_BLOCK = ( - utils.gdb_eval_or_none("CONFIG_NFILE_DESCRIPTORS_PER_BLOCK") or 8 + int(utils.gdb_eval_or_none("CONFIG_NFILE_DESCRIPTORS_PER_BLOCK")) or 8 ) g_special_inodes = {} # Map of the special inodes including epoll, inotify, etc. -- Gitee From 37261cea9971a17c218b0aed388b2ca105799d1b Mon Sep 17 00:00:00 2001 From: buxiasen Date: Thu, 9 Jan 2025 22:55:40 +0800 Subject: [PATCH 078/235] nxgdb: stack check error to wanring when inconsistant VELAPLATFO-51971 For intstack & psp case, maybe sp in msp can not match Change-Id: I9d7caa3e7514a0a012b5a1f17df7ab499e6f441e Signed-off-by: buxiasen --- tools/pynuttx/nxgdb/stack.py | 10 +++++++--- tools/pynuttx/tests/test_mock_stack.py | 8 ++++---- 2 files changed, 11 insertions(+), 7 deletions(-) diff --git a/tools/pynuttx/nxgdb/stack.py b/tools/pynuttx/nxgdb/stack.py index 8d50c600aa0..77b49139e55 100644 --- a/tools/pynuttx/nxgdb/stack.py +++ b/tools/pynuttx/nxgdb/stack.py @@ -21,6 +21,7 @@ ############################################################################ import traceback +import warnings import gdb @@ -59,11 +60,14 @@ class Stack(object): ): gdb.write( - f"base: {self._stack_base}, \ - size: {self._stack_size}, sp: {self._cur_sp}\n" + f"base: {hex(self._stack_base)}, \ + size: {hex(self._stack_size)}, sp: {hex(self._cur_sp)}\n" ) - raise gdb.GdbError("Inconsistant stack size...Maybe memory corruption?") + warnings.warn( + "Inconsistant stack size...Maybe memory corruption?", + category=RuntimeWarning, + ) # TODO: check if stack ptr is located at a sane address range! diff --git a/tools/pynuttx/tests/test_mock_stack.py b/tools/pynuttx/tests/test_mock_stack.py index bfbe149eafd..5be5f57ee36 100644 --- a/tools/pynuttx/tests/test_mock_stack.py +++ b/tools/pynuttx/tests/test_mock_stack.py @@ -32,7 +32,7 @@ class TestStack(unittest.TestCase): """ def test_stack_init_badsize(self): - with self.assertRaises(gdb.GdbError): + with self.assertWarns(RuntimeWarning): name = "test_thread" entry = hex(0xABCD) base = 0x2000 @@ -43,7 +43,7 @@ class TestStack(unittest.TestCase): Stack(name, entry, base, alloc, size, cursp, align) def test_stack_init_bad_allocaddr(self): - with self.assertRaises(gdb.GdbError): + with self.assertWarns(RuntimeWarning): name = "test_thread" entry = hex(0xABCD) alloc = 0x1000 @@ -54,7 +54,7 @@ class TestStack(unittest.TestCase): Stack(name, entry, base, alloc, size, cursp, align) def test_stack_init_bad_sp(self): - with self.assertRaises(gdb.GdbError): + with self.assertWarns(RuntimeWarning): name = "test_thread" entry = hex(0xABCD) base = 0x2000 @@ -64,7 +64,7 @@ class TestStack(unittest.TestCase): align = 4 Stack(name, entry, base, alloc, size, cursp, align) - with self.assertRaises(gdb.GdbError): + with self.assertWarns(RuntimeWarning): name = "test_thread" entry = hex(0xABCD) base = 0x2000 -- Gitee From d2f11869079d35d7d07724494cc56270c6ca931c Mon Sep 17 00:00:00 2001 From: xuxingliang Date: Tue, 21 Jan 2025 21:42:55 +0800 Subject: [PATCH 079/235] nxgdb/thread: fix remote register parsing VELAPLATFO-52621 On sim, the command line output has no space prefix. Make the regular expression to include possible prefix and suffix characters. Change-Id: I23dd1d4333431ad3c3413351bdf08541afc183e1 Signed-off-by: xuxingliang (cherry picked from commit cd81242b8e8ed5a2eac9b93551f503513e528f25) --- tools/pynuttx/nxgdb/thread.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/tools/pynuttx/nxgdb/thread.py b/tools/pynuttx/nxgdb/thread.py index 023edbc4949..e0754db49ed 100644 --- a/tools/pynuttx/nxgdb/thread.py +++ b/tools/pynuttx/nxgdb/thread.py @@ -62,10 +62,9 @@ class Registers: for line in lines.splitlines()[1:]: if not line: continue - # Name Nr Rel Offset Size Type Rmt Nr g/G Offset match = re.match( - r"\s(\S+)\s+(\d+)\s+(\d+)\s+(\d+)\s+(\d+)\s+(\S+)(?:\s+(\d+)\s+(\d+))?", + r".*?(\S+)\s+(\d+)\s+(\d+)\s+(\d+)\s+(\d+)\s+(\S+)(?:\s+(\d+)\s+(\d+))?.*?", line, ) if not match: -- Gitee From 71ccf358d031c3963b7dba8f3bc121a38fb6d9b2 Mon Sep 17 00:00:00 2001 From: xuxingliang Date: Sat, 8 Feb 2025 16:43:49 +0800 Subject: [PATCH 080/235] nxgdb: remove TypeAlias VELAPLATFO-53324 Using it requires to install typing-extensions on some versions of GDB. Remove it to avoid bothering everyone just for a type hint. Change-Id: I628347637f4b498992f8153f4e7335aa446f51e5 Signed-off-by: xuxingliang --- tools/pynuttx/nxgdb/utils.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/tools/pynuttx/nxgdb/utils.py b/tools/pynuttx/nxgdb/utils.py index 692ffaca835..79f4b9aea46 100644 --- a/tools/pynuttx/nxgdb/utils.py +++ b/tools/pynuttx/nxgdb/utils.py @@ -35,7 +35,6 @@ from typing import List, Optional, Tuple, Union import gdb from nxelf.macros import fetch_macro_info, try_expand -from typing_extensions import TypeAlias from .protocols.thread import Tcb @@ -43,7 +42,7 @@ g_symbol_cache = {} g_type_cache = {} g_macro_ctx = None g_backtrace_cache = {} -TypeOrStr: TypeAlias = Union[gdb.Type, str] +TypeOrStr = Union[gdb.Type, str] class Value(gdb.Value): -- Gitee From 1472d39cbd268c67bd6ca9c50ce09e7a742ce0c3 Mon Sep 17 00:00:00 2001 From: xuxingliang Date: Wed, 22 Jan 2025 19:49:22 +0800 Subject: [PATCH 081/235] nxstub: fix cannot read symbol when LTO is used VELAPLATFO-52867 The symbol name is suffixed with .lto_priv.0 suffix. Need to only match the symbol name without suffix. Change-Id: I58940c067bb1bed99f390c25ab9b0a3a7b835a64 Signed-off-by: xuxingliang --- tools/pynuttx/nxstub/utils.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/tools/pynuttx/nxstub/utils.py b/tools/pynuttx/nxstub/utils.py index 830acee597e..94e8d7e4e57 100644 --- a/tools/pynuttx/nxstub/utils.py +++ b/tools/pynuttx/nxstub/utils.py @@ -100,13 +100,15 @@ def read_from(elf: lief.Binary, addr, len=1) -> memoryview: def get_symbol(elf: lief.Binary, symbol) -> lief.Symbol: - return elf.get_symbol(symbol) + for sym in elf.symbols: + if sym.name.split(".")[0] == symbol: + return sym def read_symbol( elf: lief.Binary, symbol, struct: Construct = None ) -> Tuple[lief.Symbol, memoryview]: - sym = elf.get_symbol(symbol) + sym = get_symbol(elf, symbol) if sym is None: return None -- Gitee From 76baf066a255f3f2785c481a6b1c371298c4329d Mon Sep 17 00:00:00 2001 From: xuxingliang Date: Wed, 22 Jan 2025 19:44:06 +0800 Subject: [PATCH 082/235] nxstub: add elf class around lief parsed elf VELAPLATFO-52867 We mainly use lief package to parse elf, 1. to get symbol address and value by name 2. read memory, either from elf or core 3. read elf header information Since we have to work around several issue for lief, now we add LiefELF class to hide the details. Change-Id: I2eff00d144428fe9d278a86baf903758fa524821 Signed-off-by: xuxingliang --- tools/pynuttx/nxstub/__init__.py | 4 +- tools/pynuttx/nxstub/registers.py | 2 +- tools/pynuttx/nxstub/target.py | 16 +-- tools/pynuttx/nxstub/utils.py | 200 ++++++++++++++---------------- 4 files changed, 102 insertions(+), 120 deletions(-) diff --git a/tools/pynuttx/nxstub/__init__.py b/tools/pynuttx/nxstub/__init__.py index 9949f2e451f..5a0bebd9efc 100644 --- a/tools/pynuttx/nxstub/__init__.py +++ b/tools/pynuttx/nxstub/__init__.py @@ -129,11 +129,11 @@ def gdbstub_start(args): memories.append(RawMemory(address, f.read())) print(f"Add memory dump: {memories[-1]}") - elf = utils.parse_elf(args.elffile) + elf = utils.LiefELF(args.elffile) registers, mem = parse_log(elf, args.arch, args.log) memories.extend(mem) - core = utils.parse_elf(args.core) if args.core else None + core = utils.LiefELF(args.core) if args.core else None memremap = [] if args.remap: diff --git a/tools/pynuttx/nxstub/registers.py b/tools/pynuttx/nxstub/registers.py index ec982f8e767..f7c9f8485fc 100644 --- a/tools/pynuttx/nxstub/registers.py +++ b/tools/pynuttx/nxstub/registers.py @@ -308,7 +308,7 @@ class Registers: self.logger = logging.getLogger(__name__) self.arch = arch self._registers: List[Register] = [] - regsize = utils.get_pointer_size(elf) + regsize = elf.get_pointer_size() reginfo = utils.get_reginfo(elf) layouts = g_reg_table.get(self.arch, {}).get("registers", []) regoffsets = [r.tcb_offset for r in reginfo if r.tcb_offset != UINT16_MAX] diff --git a/tools/pynuttx/nxstub/target.py b/tools/pynuttx/nxstub/target.py index 786c1f334eb..ed5116d752f 100644 --- a/tools/pynuttx/nxstub/target.py +++ b/tools/pynuttx/nxstub/target.py @@ -79,8 +79,8 @@ class Target: :param core: The optional core dump file path. """ self.logger = logging.getLogger(__name__) - self.elf = elf - self.core = core + self.elf: utils.LiefELF = elf + self.core: utils.LiefELF = core self.registers = registers or Registers(elf, arch=arch) self.memories: List[RawMemory] = [] self.arch = arch @@ -93,12 +93,12 @@ class Target: self.logger.debug(f"Memory regions: {self.memories}") def _read_symbol(self, symbol: str, length: int = 0) -> bytes: - sym = utils.get_symbol(self.elf, symbol) + sym = self.elf.get_symbol(symbol) data = self.memory_read(sym.value, length or sym.size) return data, sym def _read_int(self, symbol: str) -> int: - inttype = utils.get_inttype(self.elf) + inttype = self.elf.get_inttype() data, sym = self._read_symbol(symbol, inttype.sizeof()) if not data: return None, sym @@ -118,7 +118,7 @@ class Target: self.threads = (ThreadInfo("main", self.PID0_ID, "Running", self.registers),) try: - pointer = utils.get_pointer_type(self.elf) + pointer = self.elf.get_pointer_type() tcbsize = utils.get_tcb_size(self.elf) tcbinfo = utils.get_tcbinfo(self.elf) try: @@ -238,11 +238,11 @@ class Target: return mem.data[offset : offset + length] # Try core - if self.core and (value := utils.read_from(self.core, address, length)): + if self.core and (value := self.core.read_from(address, length)): return bytes(value) # Try elf - return bytes(utils.read_from(self.elf, address, length) or []) + return bytes(self.elf.read_from(address, length) or []) def memory_write(self, address, data): memories = self.memories @@ -296,7 +296,7 @@ class Target: ) except ValueError: # try if it's a symbol, note that expression is not supported. - address = utils.get_symbol(self.elf, address).value + address = self.elf.get_symbol(address).value self.registers.load(self.memory_read(address, utils.get_regsize(self.elf))) return f"Loaded registers from {address:#x}\n" diff --git a/tools/pynuttx/nxstub/utils.py b/tools/pynuttx/nxstub/utils.py index 94e8d7e4e57..9678a4961d2 100644 --- a/tools/pynuttx/nxstub/utils.py +++ b/tools/pynuttx/nxstub/utils.py @@ -38,7 +38,6 @@ try: except ImportError: print('Package missing, please do "pip install lief construct"') -import logging from typing import List, Tuple @@ -55,125 +54,110 @@ class RegInfo: return f"REG({self.name}, {self.size}, {self.tcb_offset})" -def parse_elf(elf_file: str) -> lief.Binary: - elf = lief.parse(elf_file) +class LiefELF: + def __init__(self, filename): + self.elf = lief.parse(filename) + if not self.elf: + raise BaseException(f"Failed to parse ELF file: {filename}") + + self.symbols = {sym.name.split(".")[0]: sym for sym in self.elf.symbols} + self.endian = ( + "l" + if self.elf.abstract.header.endianness == lief.Header.ENDIANNESS.LITTLE + else "b" + ) + self.architecture = self.elf.abstract.header.architecture + self.bits = 64 if self.elf.abstract.header.is_64 else 32 + + def get_symbol(self, symbol): + return self.symbols.get(symbol) + + def read_symbol( + self, symbol, struct: Construct = None + ) -> Tuple[lief.Symbol, memoryview]: + sym = self.get_symbol(symbol) + if sym is None: + return None + + data = self.read_from(sym.value, sym.size) + if struct: + data = struct.parse(data) + return sym, data + + def read_from(self, addr, len=1) -> memoryview: + for section in self.elf.sections: + if section.type == lief.ELF.Section.TYPE.PROGBITS: + off = addr - section.virtual_address + if ( + section.virtual_address + <= addr + < section.virtual_address + section.size + and section.size - off >= len + ): + return section.content[off : off + len] + + for segment in self.elf.segments: + if segment.type == lief.ELF.Segment.TYPE.LOAD: + off = addr - segment.virtual_address + if ( + segment.virtual_address + <= addr + < segment.virtual_address + segment.virtual_size + and segment.virtual_size - off >= len + ): + return segment.content[off : off + len] - if not elf: - logging.error(f"Failed to parse ELF file: {elf_file}") return None - return elf - - -def get_architecture(elf: lief.Binary): - return elf.abstract.header.architecture - - -def get_endian(elf: lief.Binary) -> str: - return ( - "l" if elf.abstract.header.endianness == lief.Header.ENDIANNESS.LITTLE else "b" - ) - - -def read_from(elf: lief.Binary, addr, len=1) -> memoryview: - for section in elf.sections: - if section.type == lief.ELF.Section.TYPE.PROGBITS: - off = addr - section.virtual_address - if ( - section.virtual_address <= addr < section.virtual_address + section.size - and section.size - off >= len - ): - return section.content[off : off + len] - - for segment in elf.segments: - if segment.type == lief.ELF.Segment.TYPE.LOAD: - off = addr - segment.virtual_address - if ( - segment.virtual_address - <= addr - < segment.virtual_address + segment.virtual_size - and segment.virtual_size - off >= len - ): - return segment.content[off : off + len] - - return None - - -def get_symbol(elf: lief.Binary, symbol) -> lief.Symbol: - for sym in elf.symbols: - if sym.name.split(".")[0] == symbol: - return sym - - -def read_symbol( - elf: lief.Binary, symbol, struct: Construct = None -) -> Tuple[lief.Symbol, memoryview]: - sym = get_symbol(elf, symbol) - if sym is None: - return None - - data = read_from(elf, sym.value, sym.size) - if struct: - data = struct.parse(data) - return sym, data - - -def read_string(elf: lief.Binary, addr): - """Read const string from ELF file""" - output = b"" - while True: - c = read_from(elf, addr, 1) - if c == b"\0": - break - - output += c.tobytes() - addr += 1 - - return output.decode("utf-8") - + def read_string(self, addr) -> str: + """Read const string from ELF file""" + output = b"" + while True: + c = self.read_from(addr, 1) + if c == b"\0": + break -def get_inttype(elf: lief.Binary) -> Construct: - endian = get_endian(elf) - bits = 64 if elf.abstract.header.is_64 else 32 - return { - "32l": Int32sl, - "32b": Int32sb, - "64l": Int64sl, - "64b": Int64sb, - }.get(f"{bits}{endian}", Int32sl) + output += c.tobytes() + addr += 1 + return output.decode("utf-8") -def get_pointer_type(elf: lief.Binary) -> Construct: - endian = get_endian(elf) - bits = 64 if elf.abstract.header.is_64 else 32 - return { - "32l": Int32ul, - "32b": Int32ub, - "64l": Int64ul, - "64b": Int64ub, - }.get(f"{bits}{endian}", Int32ul) + def get_inttype(self) -> Construct: + return { + "32l": Int32sl, + "32b": Int32sb, + "64l": Int64sl, + "64b": Int64sb, + }.get(f"{self.bits}{self.endian}", Int32sl) + def get_pointer_type(self) -> Construct: + return { + "32l": Int32ul, + "32b": Int32ub, + "64l": Int64ul, + "64b": Int64ub, + }.get(f"{self.bits}{self.endian}", Int32ul) -def get_pointer_size(elf: lief.Binary): - return 8 if elf.abstract.header.is_64 else 4 + def get_pointer_size(self): + return 8 if self.elf.abstract.header.is_64 else 4 -def get_ncpus(elf: lief.Binary) -> int: +def get_ncpus(elf: LiefELF) -> int: # FAR struct tcb_s *g_running_tasks[CONFIG_SMP_NCPUS]; # # g_running_tasks is an pointer array in length of ncpu g_running_tasks = elf.get_symbol("g_running_tasks") - return g_running_tasks.size // get_pointer_size(elf) + return g_running_tasks.size // elf.get_pointer_size() -def get_regsize(elf: lief.Binary) -> int: +def get_regsize(elf: LiefELF) -> int: """Register size in context""" sym = elf.get_symbol("g_last_regs") return sym.size // get_ncpus(elf) -def get_tcbinfo(elf: lief.Binary): +def get_tcbinfo(elf: LiefELF): tcbinfo_s = Struct( "pid_off" / Int16ul, # FIXME: only little endian supported "state_off" / Int16ul, @@ -185,11 +169,11 @@ def get_tcbinfo(elf: lief.Binary): "regs_num" / Int16ul, ) - _, data = read_symbol(elf, "g_tcbinfo") + _, data = elf.read_symbol("g_tcbinfo") return tcbinfo_s.parse(data) -def get_tcb_size(elf: lief.Binary) -> int: +def get_tcb_size(elf: LiefELF) -> int: # static struct tcb_s g_idletcb[CONFIG_SMP_NCPUS]; # Idle TCB happen to be an array of tcb_s @@ -198,24 +182,22 @@ def get_tcb_size(elf: lief.Binary) -> int: return g_idletcb.size // ncpus -def get_reginfo(elf: lief.Binary) -> List[RegInfo]: - bits = 64 if elf.abstract.header.is_64 else 32 - +def get_reginfo(elf: LiefELF) -> List[RegInfo]: # Now get register offset in TCB - _, data = read_symbol(elf, "g_reg_offs") + _, data = elf.read_symbol("g_reg_offs") reg_offs = Array(len(data) // 2, Int16ul).parse(data) - return [RegInfo("", bits // 8, off) for off in reg_offs] + return [RegInfo("", elf.bits // 8, off) for off in reg_offs] def parse_array(data, type_, narray): return Array(narray, type_).parse(data) -def get_statenames(elf: lief.Binary) -> List[str]: - pointer = get_pointer_type(elf) - sym, addr = read_symbol(elf, "g_statenames") +def get_statenames(elf: LiefELF) -> List[str]: + pointer = elf.get_pointer_type() + sym, addr = elf.read_symbol("g_statenames") names = parse_array(addr, pointer, sym.size // pointer.sizeof()) - names = [read_string(elf, name) for name in names] + names = [elf.read_string(name) for name in names] return names -- Gitee From fb1b50e07f6941bc52b4fb90a7399d1a2c441d07 Mon Sep 17 00:00:00 2001 From: xuxingliang Date: Sat, 8 Feb 2025 16:55:08 +0800 Subject: [PATCH 083/235] pynuttx: ignore non-unicode in text file during parsing VELAPLATFO-53324 The log file from device may contain invalid unicode, we can simply ignore those and continue. Change-Id: I81e365b0b18020fbf39e857db85aad7ba862ccb6 Signed-off-by: xuxingliang --- tools/pynuttx/nxgdb/memdump.py | 2 +- tools/pynuttx/nxstub/__init__.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/tools/pynuttx/nxgdb/memdump.py b/tools/pynuttx/nxgdb/memdump.py index 8374b0cd9a8..77a7c5ccd14 100644 --- a/tools/pynuttx/nxgdb/memdump.py +++ b/tools/pynuttx/nxgdb/memdump.py @@ -187,7 +187,7 @@ def parse_memdump_log(logfile, filters=None) -> Generator[MMNodeDump, None, None None, ) - with open(logfile) as f: + with open(logfile, "r", errors="ignore") as f: for line in f: match = re.search( r"(\d+)\s+(\d+)\s+(\d+)\s+(\d+)((?:\s+0x[0-9a-fA-F]+)+)", line diff --git a/tools/pynuttx/nxstub/__init__.py b/tools/pynuttx/nxstub/__init__.py index 5a0bebd9efc..b5455b34c44 100644 --- a/tools/pynuttx/nxstub/__init__.py +++ b/tools/pynuttx/nxstub/__init__.py @@ -82,7 +82,7 @@ def parse_log(elf, arch, logfile): registerdump = [] parsing_regs = False lines = [] - with open(logfile, "r") as f: + with open(logfile, "r", errors="ignore") as f: for line in f: line = line.strip() if is_register_dump(line): -- Gitee From 466a67e5e6083578eaafa30d7dc05f7da4040c03 Mon Sep 17 00:00:00 2001 From: yangao1 Date: Mon, 20 Jan 2025 21:05:46 +0800 Subject: [PATCH 084/235] pynuttx/rpmsg.py:modify prompt for rpmsgdump -t VELAPLATFO-52597 (gdb)rpmsgdump -t or rpmsgdump --transport-only Change-Id: Ib2d07956c993b0a3e7779cbd49d0b3851fb5df8b Signed-off-by: yangao1 --- tools/pynuttx/nxgdb/rpmsg.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/tools/pynuttx/nxgdb/rpmsg.py b/tools/pynuttx/nxgdb/rpmsg.py index d3ec0b3b63f..2e7ed5bd60a 100644 --- a/tools/pynuttx/nxgdb/rpmsg.py +++ b/tools/pynuttx/nxgdb/rpmsg.py @@ -172,10 +172,10 @@ class RPMsgDump(gdb.Command): ) gdb.write("\n".join(output) + "\n") - def dump_rpmsg(self, transport): + def dump_rpmsg(self, transport_only): for rpmsg in NxList(gdb.parse_and_eval("g_rpmsg"), "struct rpmsg_s", "node"): gdb.write(f"Rpmsg Device: rpmsg:{rpmsg} rdev:{rpmsg['rdev']}\n") - if not transport: + if not transport_only: self.dump_rdev(rpmsg["rdev"]) self.dump_rpmsg_virtio(rpmsg["rdev"]) @@ -183,6 +183,6 @@ class RPMsgDump(gdb.Command): if not (args := self.parse_args(args)): return - if not args.transport: + if not args.transport_only: self.dump_rpmsg_cb() - self.dump_rpmsg(args.transport) + self.dump_rpmsg(args.transport_only) -- Gitee From 06a42ea1880a8bd8d4b012e658a23ddb3cc22a02 Mon Sep 17 00:00:00 2001 From: xuxingliang Date: Wed, 22 Jan 2025 17:41:47 +0800 Subject: [PATCH 085/235] nxgdb/mm: fix memleak false positive report VELAPLATFO-52804 The whol struct mm_allocnode_s struct should be regarded as overhead, since the address points to the struct itself. Change-Id: Ia0c927061612e4b167c324c4b7671d60062ce8eb Signed-off-by: xuxingliang --- tools/pynuttx/nxgdb/mm.py | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/tools/pynuttx/nxgdb/mm.py b/tools/pynuttx/nxgdb/mm.py index a4eb5497877..eb90d5d86aa 100644 --- a/tools/pynuttx/nxgdb/mm.py +++ b/tools/pynuttx/nxgdb/mm.py @@ -383,7 +383,8 @@ class MMNode(gdb.Value, p.MMFreeNode): MM_PREVFREE_BIT = 0x2 MM_MASK_BIT = MM_ALLOC_BIT | MM_PREVFREE_BIT MM_SIZEOF_ALLOCNODE = utils.sizeof("struct mm_allocnode_s") - MM_ALLOCNODE_OVERHEAD = MM_SIZEOF_ALLOCNODE - utils.sizeof("mmsize_t") + # Although preceding can locates in the previous node, we still count it as overhead + MM_ALLOCNODE_OVERHEAD = MM_SIZEOF_ALLOCNODE MM_MIN_SHIFT = utils.log2ceil(utils.sizeof("struct mm_freenode_s")) MM_MIN_CHUNK = 1 << MM_MIN_SHIFT @@ -416,12 +417,8 @@ class MMNode(gdb.Value, p.MMFreeNode): ) def contains(self, address): - """Check if the address is in node's range, excluding oeprhead""" - return ( - self.address + self.overhead - <= address - < self.address + self.nodesize - MMNode.MM_ALLOCNODE_OVERHEAD - ) + """Check if the address is in node's range, excluding overhead""" + return self.address + self.overhead <= address < self.address + self.nodesize def read_memory(self): addr = int(self.address) + MMNode.MM_ALLOCNODE_OVERHEAD -- Gitee From 47873e7dbc892b1a01ac7ca76d3b658766490d08 Mon Sep 17 00:00:00 2001 From: xuxingliang Date: Wed, 22 Jan 2025 17:50:03 +0800 Subject: [PATCH 086/235] nxgdb/worker: print the struct type and address VELAPLATFO-47928 To make it easier to inspect data structure. Change-Id: Icb1a6f50cf387abeaa5eaa56d4f65a81b2e21e14 Signed-off-by: xuxingliang --- tools/pynuttx/nxgdb/wqueue.py | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/tools/pynuttx/nxgdb/wqueue.py b/tools/pynuttx/nxgdb/wqueue.py index 52abf553a25..9e4f60d74da 100644 --- a/tools/pynuttx/nxgdb/wqueue.py +++ b/tools/pynuttx/nxgdb/wqueue.py @@ -42,7 +42,7 @@ class Work(Value, p.Work): return WorkQueue(self.wq) def __repr__(self) -> str: - return f"work_s@{self.address:#x}: {self.worker.format_string(styling=True)} arg={self.arg}" + return f"(struct work_s *){self.address:#x}: {self.worker.format_string(styling=True)} arg={self.arg}" def __str__(self) -> str: return self.__repr__() @@ -71,7 +71,7 @@ class KWorker(Value, p.KWorker): return utils.get_task_name(utils.get_tcb(self.pid)) def __repr__(self): - return f"kworker_s@{self.address:#x} {self.work or 'idle'}" + return f"(struct kworker_s *){self.address:#x} {self.work or 'idle'}" def __str__(self): return self.__repr__() @@ -114,7 +114,10 @@ class WorkQueue(Value, p.KWorkQueue): def __repr__(self): state = "running" if self.is_running else "idle" - return f"{self.name}@{self.address:#x}, {state}, {self.nthreads} threads, {len(self.workers)} work" + return ( + f"{self.name} (struct kwork_wqueue_s *){self.address:#x}, {state}, " + f"{self.nthreads} threads, {len(self.workers)} work" + ) def __str__(self): return self.__repr__() -- Gitee From b82ae344a8da62c9f64ac119bc8cb8b898a061e8 Mon Sep 17 00:00:00 2001 From: xuxingliang Date: Thu, 30 Jan 2025 20:22:36 +0800 Subject: [PATCH 087/235] nxgdb: fix info nxthreads to read current PC VELAPLATFO-53048 Although GDB has a unifed register SP/PC for all architecture, we need the real register name so we can read register from TCB's saved context. GDB's python API can find all the registers but unfortunetly cannot be used to distinguish which register is the real PC/SP, so we we have to hardcode the name as a table using arch as key. Change-Id: I9004960cbc1e4cebc750f837f2aef3e597b754f2 Signed-off-by: xuxingliang --- tools/pynuttx/nxgdb/utils.py | 20 ++++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/tools/pynuttx/nxgdb/utils.py b/tools/pynuttx/nxgdb/utils.py index 79f4b9aea46..0772320d9ba 100644 --- a/tools/pynuttx/nxgdb/utils.py +++ b/tools/pynuttx/nxgdb/utils.py @@ -778,11 +778,27 @@ def get_register_byname(regname, tcb=None): def get_sp(tcb=None): - return get_register_byname("sp", tcb) + regname = "sp" + if tcb is not None: + # NuttX doesn't support unified register name for stack pointer + arch = gdb.selected_inferior().architecture().name() + regname = { + "i386:x86": "esp", + "i386:x86-64": "rsp", + }.get(arch, "sp") + return get_register_byname(regname, tcb) def get_pc(tcb=None): - return get_register_byname("pc", tcb) + regname = "pc" + if tcb is not None: + # NuttX doesn't support unified register name for PC + arch = gdb.selected_inferior().architecture().name() + regname = { + "i386:x86": "eip", + "i386:x86-64": "rip", + }.get(arch, "pc") + return get_register_byname(regname, tcb) def get_tcbs() -> List[Tcb]: -- Gitee From 22c70c7f76af98bdcef9cf1186abb0fb0f0a8ff3 Mon Sep 17 00:00:00 2001 From: xuxingliang Date: Thu, 30 Jan 2025 20:04:22 +0800 Subject: [PATCH 088/235] nxgdb/thread: use reginfo to switch threads from python VELAPLATFO-53264 Registers are needed for threads command, previously we use complex method to match NuttX reginfo with GDB's register. Now C code provides register name, together with its size, and offset in TCB. Change-Id: I089b2ba8e6643031006b625b556b5e7044acc052 Signed-off-by: xuxingliang --- tools/pynuttx/nxgdb/thread.py | 55 +++++------------------------------ tools/pynuttx/nxgdb/utils.py | 26 +++++++---------- 2 files changed, 19 insertions(+), 62 deletions(-) diff --git a/tools/pynuttx/nxgdb/thread.py b/tools/pynuttx/nxgdb/thread.py index e0754db49ed..15cba73a09c 100644 --- a/tools/pynuttx/nxgdb/thread.py +++ b/tools/pynuttx/nxgdb/thread.py @@ -21,7 +21,6 @@ ############################################################################ import argparse -import re from enum import Enum, auto import gdb @@ -49,55 +48,17 @@ class Registers: if not Registers.reginfo: reginfo = {} - # Switch to second inferior to get the original remote-register layout - state = utils.suppress_cli_notifications(True) - utils.switch_inferior(2) - - natural_size = gdb.lookup_type("long").sizeof - tcb_info = gdb.parse_and_eval("g_tcbinfo") - reg_off = tcb_info["reg_off"]["p"] # Register offsets in tcbinfo - packet_size = tcb_info["regs_num"] * natural_size - - lines = gdb.execute("maint print remote-registers", to_string=True) - for line in lines.splitlines()[1:]: - if not line: - continue - # Name Nr Rel Offset Size Type Rmt Nr g/G Offset - match = re.match( - r".*?(\S+)\s+(\d+)\s+(\d+)\s+(\d+)\s+(\d+)\s+(\S+)(?:\s+(\d+)\s+(\d+))?.*?", - line, - ) - if not match: - continue - - name, _, _, _, size, _, rmt_nr, offset = match.groups() - - # We only need those registers that have a remote register - if rmt_nr is None: - continue - - rmt_nr = int(rmt_nr) - offset = int(offset) - size = int(size) - - # We only have limited number of registers in packet - if offset + size > packet_size: - continue - - index = offset // natural_size - tcb_reg_off = int(reg_off[index]) - if tcb_reg_off == UINT16_MAX: - # This register is not saved in tcb context - continue - - reginfo[name] = { - "rmt_nr": rmt_nr, # The register number in remote-registers, Aka the one we saved in g_tcbinfo. - "tcb_reg_off": tcb_reg_off, + tcb_info = utils.parse_and_eval("g_tcbinfo") + reg_info = tcb_info.u.reginfo + reginfo = { + str(reg.name.string()): { + "rmt_nr": int(reg.regnum), + "tcb_reg_off": int(reg.toffset), } + for reg in utils.ArrayIterator(reg_info, tcb_info.regs_num) + } Registers.reginfo = reginfo - utils.switch_inferior(1) # Switch back - utils.suppress_cli_notifications(state) def load(self, regs): """Load registers from context register address""" diff --git a/tools/pynuttx/nxgdb/utils.py b/tools/pynuttx/nxgdb/utils.py index 0772320d9ba..4ca0fb54e90 100644 --- a/tools/pynuttx/nxgdb/utils.py +++ b/tools/pynuttx/nxgdb/utils.py @@ -760,21 +760,17 @@ def get_register_byname(regname, tcb=None): return int(frame.read_register(regname)) # Ok, let's take it from the context in the given tcb - arch = frame.architecture() - tcbinfo = gdb.parse_and_eval("g_tcbinfo") - - i = 0 - for reg in arch.registers(): - if reg.name == regname: - break - i += 1 - - regs = tcb["xcp"]["regs"].cast(gdb.lookup_type("char").pointer()) - value = gdb.Value(regs + tcbinfo["reg_off"]["p"][i]).cast( - gdb.lookup_type("uintptr_t").pointer() - )[0] - - return int(value) + tcbinfo = parse_and_eval("g_tcbinfo") + + for reg in ArrayIterator(tcbinfo.u.reginfo, tcbinfo.regs_num): + if reg.name.string().lower() == regname.lower(): + xcpregs = tcb["xcp"]["regs"] + if xcpregs.type.code != gdb.TYPE_CODE_PTR: + # For sim, the xcpregs is an array, not pointer, thus need casting + xcpregs = xcpregs.cast(lookup_type("char").pointer()) + value = gdb.Value(int(xcpregs) + reg.toffset) + value = value.cast(lookup_type("uintptr_t").pointer()) + return int(value.dereference()) def get_sp(tcb=None): -- Gitee From 80cc76bd6fe0bde5ccaead7e9c555697a8ff781a Mon Sep 17 00:00:00 2001 From: xuxingliang Date: Sat, 8 Feb 2025 10:50:38 +0800 Subject: [PATCH 089/235] nxgdb/thread: use g_running_tasks instead of function call VELAPLATFO-53274 Previously the function tcbinfo_running_regs is added to avoid optimization out of g_running_task. But this means GDB has to execute the function in order to get running regs. (gdb) bt #0 tcbinfo_current_regs () at ../../../fs/procfs/fs_procfstcbinfo.c:191 #1 #2 nxsem_wait_slow (sem=0x20084cb4 ) at ../../../sched/semaphore/sem_wait.c:203 #3 nxsem_wait (sem=sem@entry=0x20084cb4 ) at ../../../sched/semaphore/sem_wait.c:273 #4 0x10a0d8b8 in nxsem_wait_uninterruptible (sem=sem@entry=0x20084cb4 ) at ../../../sched/semaphore/sem_wait.c:301 #5 0x10a0f2a0 in work_thread (argc=, argv=) at ../../../sched/wqueue/kwork_thread.c:214 #6 0x10a0f184 in nxtask_start () at ../../../sched/task/task_start.c:111 #7 0x00000000 in ?? () (gdb) Now we remove the dependency and use g_running_tasks directly since it's now used in multiple places including doirq etc, thus not likely to be optimized out. Change-Id: I387a40d15491718ce66fe75cb928a94c6aea9bc6 Signed-off-by: xuxingliang --- tools/pynuttx/nxgdb/thread.py | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/tools/pynuttx/nxgdb/thread.py b/tools/pynuttx/nxgdb/thread.py index 15cba73a09c..f4bf4edebce 100644 --- a/tools/pynuttx/nxgdb/thread.py +++ b/tools/pynuttx/nxgdb/thread.py @@ -119,14 +119,15 @@ g_registers = Registers() class SetRegs(gdb.Command): - """Set registers to the specified values. + """Load registers from TCB context memory address. Usage: setregs [regs] Etc: setregs setregs tcb->xcp.regs setregs g_pidhash[0]->xcp.regs - Default regs is tcbinfo_running_regs(),if regs is NULL, it will not set registers. + Default to load from g_running_tasks if no args are provided. + If the memory address is NULL, it will not set registers. """ def __init__(self): @@ -141,7 +142,7 @@ class SetRegs(gdb.Command): "regs", nargs="?", default="", - help="The registers to set, use tcbinfo_running_regs() if not specified", + help="The memory address to load register values, use g_running_tasks.xcp.regs if not specified", ) try: @@ -154,7 +155,12 @@ class SetRegs(gdb.Command): utils.lookup_type("char").pointer() ) else: - current_regs = gdb.parse_and_eval("tcbinfo_running_regs()") + try: + current_regs = gdb.parse_and_eval("g_running_tasks[0].xcp.regs") + except gdb.error as e: + gdb.write(f"Failed to parse running tasks: {e}\n") + return + regs = current_regs.cast(utils.lookup_type("char").pointer()) if regs == 0: -- Gitee From 6dc5769a53e5339de05eeff41b7eb09a01bf9b2f Mon Sep 17 00:00:00 2001 From: xuxingliang Date: Sat, 8 Feb 2025 09:48:04 +0800 Subject: [PATCH 090/235] nxgdb: ignore ctrl+C interrupt signal in gdbstub thread VELAPLATFO-53263 So when we use ctrl+c to stop an ongoing command, GDB stub won't be affected. Change-Id: I41c9839c74f2a97d52950a280c2f296d6348c2bc Signed-off-by: xuxingliang --- tools/pynuttx/nxgdb/target.py | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/tools/pynuttx/nxgdb/target.py b/tools/pynuttx/nxgdb/target.py index 29b92a665a3..9e9c6a952a8 100644 --- a/tools/pynuttx/nxgdb/target.py +++ b/tools/pynuttx/nxgdb/target.py @@ -67,7 +67,14 @@ class Target(gdb.Command): kill() - process = multiprocessing.Process(target=nxstub.main, args=(args,)) + def stub_main(args): + import signal + + # Ignore the Ctrl+C signal + signal.signal(signal.SIGINT, signal.SIG_IGN) + nxstub.main(args) + + process = multiprocessing.Process(target=stub_main, args=(args,)) process.start() self.process = process -- Gitee From d4ba2ad8384b429fe5b6b0c10eda8746706a1b3a Mon Sep 17 00:00:00 2001 From: xuxingliang Date: Sat, 8 Feb 2025 19:48:32 +0800 Subject: [PATCH 091/235] nxgdb: fix i386 parsing PC/SP VELAPLATFO-53324 GDB sometimes uses i386 directly withou :x86 suffix for 32bit Change-Id: Ib5c97bb94bdc39d2f75588c26200509625d1ec38 Signed-off-by: xuxingliang --- tools/pynuttx/nxgdb/utils.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tools/pynuttx/nxgdb/utils.py b/tools/pynuttx/nxgdb/utils.py index 4ca0fb54e90..e086bb8267b 100644 --- a/tools/pynuttx/nxgdb/utils.py +++ b/tools/pynuttx/nxgdb/utils.py @@ -779,6 +779,7 @@ def get_sp(tcb=None): # NuttX doesn't support unified register name for stack pointer arch = gdb.selected_inferior().architecture().name() regname = { + "i386": "esp", "i386:x86": "esp", "i386:x86-64": "rsp", }.get(arch, "sp") @@ -791,6 +792,7 @@ def get_pc(tcb=None): # NuttX doesn't support unified register name for PC arch = gdb.selected_inferior().architecture().name() regname = { + "i386": "eip", "i386:x86": "eip", "i386:x86-64": "rip", }.get(arch, "pc") -- Gitee From 3e3f0db73d9caecd60b8fef0cb047b904e9b1b46 Mon Sep 17 00:00:00 2001 From: yangao1 Date: Mon, 17 Feb 2025 21:22:43 +0800 Subject: [PATCH 092/235] pynuttx/elf.py:add ELFParser class from nxstub/utils.py VELAPLATFO-53625 Change-Id: Ice64b66a8c80851b4db022a52096dd38d5ab353f Signed-off-by: yangao1 --- tools/pynuttx/nxelf/elf.py | 150 +++++++++++++++++++++++++++++----- tools/pynuttx/nxstub/utils.py | 135 ++++-------------------------- 2 files changed, 146 insertions(+), 139 deletions(-) diff --git a/tools/pynuttx/nxelf/elf.py b/tools/pynuttx/nxelf/elf.py index 5ae432be093..3304a1c54e4 100644 --- a/tools/pynuttx/nxelf/elf.py +++ b/tools/pynuttx/nxelf/elf.py @@ -22,18 +22,38 @@ import logging import time from enum import IntEnum +from typing import Tuple from .macros import Macro try: - import construct import cxxfilt + import lief + from construct import ( + Array, + Construct, + Float16l, + Float32l, + Float64l, + Int8sl, + Int8ul, + Int16sl, + Int16ul, + Int32sb, + Int32sl, + Int32ub, + Int32ul, + Int64sb, + Int64sl, + Int64ub, + Int64ul, + Struct, + ) from elftools.elf.elffile import ELFFile from elftools.elf.sections import SymbolTableSection -except ModuleNotFoundError: - print("Please execute the following command to install dependencies:") - print("pip install construct pyelftools cxxfilt") - exit(1) +except ModuleNotFoundError as e: + print(f"Error:{e}.\nPlease execute the following command to install dependencies:") + print("pip install construct pyelftools cxxfilt lief ") logging.basicConfig(level=logging.WARNING) logger = logging.getLogger(__name__) @@ -197,7 +217,7 @@ class ELFParser: ) item_type = self.parse_die(type_die) - array = construct.Array(nums, item_type) + array = Array(nums, item_type) return array def parse_die(self, die): @@ -220,9 +240,9 @@ class ELFParser: return self.typedef(die.attributes["DW_AT_name"].value.decode("utf-8")) elif die.tag == "DW_TAG_pointer_type": if self.info["bitwides"] == 32: - return construct.Int32ul + return Int32ul elif self.info["bitwides"] == 64: - return construct.Int64ul + return Int64ul else: raise ValueError("Unsupported ELF class") elif die.tag == "DW_TAG_array_type": @@ -262,28 +282,28 @@ class ELFParser: size = die.attributes["DW_AT_byte_size"].value unsigned_map = { - 1: construct.Int8ul, - 2: construct.Int16ul, - 4: construct.Int32ul, - 8: construct.Int64ul, + 1: Int8ul, + 2: Int16ul, + 4: Int32ul, + 8: Int64ul, } signed_map = { - 1: construct.Int8sl, - 2: construct.Int16sl, - 4: construct.Int32sl, - 8: construct.Int64sl, + 1: Int8sl, + 2: Int16sl, + 4: Int32sl, + 8: Int64sl, } double_map = { - 2: construct.Float16l, - 4: construct.Float32l, - 8: construct.Float64l, + 2: Float16l, + 4: Float32l, + 8: Float64l, } if "unsigned" in name: return unsigned_map.get(size, None) elif "double" in name or "float" in name: return double_map.get(size, None) elif "_Bool" in name: - return construct.Int8ul + return Int8ul elif "char" in name or "short" in name or "int" in name: return signed_map.get(size, None) @@ -325,7 +345,7 @@ class ELFParser: member_type = self.parse_die(type_die) members[member_name] = member_type - struct = construct.Struct(**members) + struct = Struct(**members) if not rets or all(ret.sizeof() != struct.sizeof() for ret in rets): rets.add(struct) @@ -386,3 +406,91 @@ class ELFParser: rets.add(value) return enums.set_result(enum_name, rets) + + +class LiefELF: + def __init__(self, filename): + self.elf = lief.parse(filename) + if not self.elf: + raise BaseException(f"Failed to parse ELF file: {filename}") + + self.symbols = {sym.name.split(".")[0]: sym for sym in self.elf.symbols} + self.endian = ( + "l" + if self.elf.abstract.header.endianness == lief.Header.ENDIANNESS.LITTLE + else "b" + ) + self.architecture = self.elf.abstract.header.architecture + self.bits = 64 if self.elf.abstract.header.is_64 else 32 + + def get_symbol(self, symbol): + return self.symbols.get(symbol) + + def read_symbol( + self, symbol, struct: Construct = None + ) -> Tuple[lief.Symbol, memoryview]: + sym = self.get_symbol(symbol) + if sym is None: + return None + + data = self.read_from(sym.value, sym.size) + if struct: + data = struct.parse(data) + return sym, data + + def read_from(self, addr, len=1) -> memoryview: + for section in self.elf.sections: + if section.type == lief.ELF.Section.TYPE.PROGBITS: + off = addr - section.virtual_address + if ( + section.virtual_address + <= addr + < section.virtual_address + section.size + and section.size - off >= len + ): + return section.content[off : off + len] + + for segment in self.elf.segments: + if segment.type == lief.ELF.Segment.TYPE.LOAD: + off = addr - segment.virtual_address + if ( + segment.virtual_address + <= addr + < segment.virtual_address + segment.virtual_size + and segment.virtual_size - off >= len + ): + return segment.content[off : off + len] + + return None + + def read_string(self, addr) -> str: + """Read const string from ELF file""" + output = b"" + while True: + c = self.read_from(addr, 1) + if c == b"\0": + break + + output += c.tobytes() + addr += 1 + + return output.decode("utf-8") + + def get_inttype(self) -> Construct: + return { + "32l": Int32sl, + "32b": Int32sb, + "64l": Int64sl, + "64b": Int64sb, + }.get(f"{self.bits}{self.endian}", Int32sl) + + def get_pointer_type(self) -> Construct: + return { + "32l": Int32ul, + "32b": Int32ub, + "64l": Int64ul, + "64b": Int64ub, + }.get(f"{self.bits}{self.endian}", Int32ul) + + def get_pointer_size(self): + return 8 if self.elf.abstract.header.is_64 else 4 diff --git a/tools/pynuttx/nxstub/utils.py b/tools/pynuttx/nxstub/utils.py index 9678a4961d2..aa537c8bae4 100644 --- a/tools/pynuttx/nxstub/utils.py +++ b/tools/pynuttx/nxstub/utils.py @@ -19,127 +19,13 @@ ############################################################################ try: - import lief - from construct import ( - Array, - Construct, - Int8ul, - Int16ul, - Int32sb, - Int32sl, - Int32ub, - Int32ul, - Int64sb, - Int64sl, - Int64ub, - Int64ul, - Struct, - ) + from construct import Array, Int8ul, Int16ul, Struct except ImportError: - print('Package missing, please do "pip install lief construct"') - -from typing import List, Tuple - - -class RegInfo: - def __init__(self, name, size, tcb_offset=0): - self.name = name - self.size = size - self.tcb_offset = tcb_offset - - def __str__(self): - return f"{self.name}({self.size})" - - def __repr__(self): - return f"REG({self.name}, {self.size}, {self.tcb_offset})" - - -class LiefELF: - def __init__(self, filename): - self.elf = lief.parse(filename) - if not self.elf: - raise BaseException(f"Failed to parse ELF file: {filename}") - - self.symbols = {sym.name.split(".")[0]: sym for sym in self.elf.symbols} - self.endian = ( - "l" - if self.elf.abstract.header.endianness == lief.Header.ENDIANNESS.LITTLE - else "b" - ) - self.architecture = self.elf.abstract.header.architecture - self.bits = 64 if self.elf.abstract.header.is_64 else 32 - - def get_symbol(self, symbol): - return self.symbols.get(symbol) - - def read_symbol( - self, symbol, struct: Construct = None - ) -> Tuple[lief.Symbol, memoryview]: - sym = self.get_symbol(symbol) - if sym is None: - return None - - data = self.read_from(sym.value, sym.size) - if struct: - data = struct.parse(data) - return sym, data - - def read_from(self, addr, len=1) -> memoryview: - for section in self.elf.sections: - if section.type == lief.ELF.Section.TYPE.PROGBITS: - off = addr - section.virtual_address - if ( - section.virtual_address - <= addr - < section.virtual_address + section.size - and section.size - off >= len - ): - return section.content[off : off + len] - - for segment in self.elf.segments: - if segment.type == lief.ELF.Segment.TYPE.LOAD: - off = addr - segment.virtual_address - if ( - segment.virtual_address - <= addr - < segment.virtual_address + segment.virtual_size - and segment.virtual_size - off >= len - ): - return segment.content[off : off + len] - - return None - - def read_string(self, addr) -> str: - """Read const string from ELF file""" - output = b"" - while True: - c = self.read_from(addr, 1) - if c == b"\0": - break - - output += c.tobytes() - addr += 1 - - return output.decode("utf-8") + print('Package missing, please do "pip install construct"') - def get_inttype(self) -> Construct: - return { - "32l": Int32sl, - "32b": Int32sb, - "64l": Int64sl, - "64b": Int64sb, - }.get(f"{self.bits}{self.endian}", Int32sl) +from typing import List - def get_pointer_type(self) -> Construct: - return { - "32l": Int32ul, - "32b": Int32ub, - "64l": Int64ul, - "64b": Int64ub, - }.get(f"{self.bits}{self.endian}", Int32ul) - - def get_pointer_size(self): - return 8 if self.elf.abstract.header.is_64 else 4 +from nxelf.elf import LiefELF def get_ncpus(elf: LiefELF) -> int: @@ -157,6 +43,19 @@ def get_regsize(elf: LiefELF) -> int: return sym.size // get_ncpus(elf) +class RegInfo: + def __init__(self, name, size, tcb_offset=0): + self.name = name + self.size = size + self.tcb_offset = tcb_offset + + def __str__(self): + return f"{self.name}({self.size})" + + def __repr__(self): + return f"REG({self.name}, {self.size}, {self.tcb_offset})" + + def get_tcbinfo(elf: LiefELF): tcbinfo_s = Struct( "pid_off" / Int16ul, # FIXME: only little endian supported -- Gitee From f7048e77a74d18c874f51296b1fd82200e202dee Mon Sep 17 00:00:00 2001 From: yangao1 Date: Mon, 17 Feb 2025 20:12:36 +0800 Subject: [PATCH 093/235] nxreg/register.py:remove nxstub/register.py to nxreg VELAPLATFO-53625 Change-Id: I79305b89d06c8c31af1b524e392b522be93f862e Signed-off-by: yangao1 --- tools/pynuttx/nxreg/__init__.py | 19 ++ tools/pynuttx/nxreg/register.py | 422 ++++++++++++++++++++++++++++++ tools/pynuttx/nxstub/__init__.py | 3 +- tools/pynuttx/nxstub/registers.py | 389 --------------------------- tools/pynuttx/nxstub/target.py | 3 +- tools/pynuttx/nxstub/utils.py | 20 -- 6 files changed, 445 insertions(+), 411 deletions(-) create mode 100644 tools/pynuttx/nxreg/__init__.py create mode 100644 tools/pynuttx/nxreg/register.py diff --git a/tools/pynuttx/nxreg/__init__.py b/tools/pynuttx/nxreg/__init__.py new file mode 100644 index 00000000000..bb1fc7414c7 --- /dev/null +++ b/tools/pynuttx/nxreg/__init__.py @@ -0,0 +1,19 @@ +############################################################################ +# tools/pynuttx/nxreg/__init__.py +# +# Licensed to the Apache Software Foundation (ASF) under one or more +# contributor license agreements. See the NOTICE file distributed with +# this work for additional information regarding copyright ownership. The +# ASF licenses this file to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance with the +# License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# +############################################################################ diff --git a/tools/pynuttx/nxreg/register.py b/tools/pynuttx/nxreg/register.py new file mode 100644 index 00000000000..e5525703fe2 --- /dev/null +++ b/tools/pynuttx/nxreg/register.py @@ -0,0 +1,422 @@ +############################################################################ +# tools/pynuttx/nxreg/register.py +# +# Licensed to the Apache Software Foundation (ASF) under one or more +# contributor license agreements. See the NOTICE file distributed with +# this work for additional information regarding copyright ownership. The +# ASF licenses this file to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance with the +# License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# +############################################################################ + +import logging +from binascii import hexlify +from typing import List, Union + +from construct import Array, Int16ul +from nxelf.elf import LiefELF + +UINT16_MAX = 0xFFFF + +g_reg_table = { + "arm": { + "architecture": "arm", + "feature": "org.gnu.gdb.arm.m-profile", + "registers": [ + ("r0", 0, 0), + ("r1", 1, 0), + ("r2", 2, 0), + ("r3", 3, 0), + ("r4", 4, 0), + ("r5", 5, 0), + ("r6", 6, 0), + ("fp", 7, 0), + ("r8", 8, 0), + ("sb", 9, 0), + ("sl", 10, 0), + ("r11", 11, 0), + ("ip", 12, 0), + ("sp", 13, 0), + ("lr", 14, 0), + ("pc", 15, 0), + ("xpsr", 16, 0), + ], + }, + "arm-a": { + "architecture": "arm", + "feature": "org.gnu.gdb.arm", + "registers": [ + ("r0", 0, 0), + ("r1", 1, 0), + ("r2", 2, 0), + ("r3", 3, 0), + ("r4", 4, 0), + ("r5", 5, 0), + ("r6", 6, 0), + ("fp", 7, 0), + ("r8", 8, 0), + ("sb", 9, 0), + ("sl", 10, 0), + ("r11", 11, 0), + ("ip", 12, 0), + ("sp", 13, 0), + ("lr", 14, 0), + ("pc", 15, 0), + ("cpsr", 25, 164), + ], + }, + "arm64": { + "architecture": "aarch64", + "feature": "org.gnu.gdb.aarch64", + "registers": [ + ("x0", 0, 0), + ("x1", 1, 0), + ("x2", 2, 0), + ("x3", 3, 0), + ("x4", 4, 0), + ("x5", 5, 0), + ("x6", 6, 0), + ("x7", 7, 0), + ("x8", 8, 0), + ("x9", 9, 0), + ("x10", 10, 0), + ("x11", 11, 0), + ("x12", 12, 0), + ("x13", 13, 0), + ("x14", 14, 0), + ("x15", 15, 0), + ("x16", 16, 0), + ("x17", 17, 0), + ("x18", 18, 0), + ("x19", 19, 0), + ("x20", 20, 0), + ("x21", 21, 0), + ("x22", 22, 0), + ("x23", 23, 0), + ("x24", 24, 0), + ("x25", 25, 0), + ("x26", 26, 0), + ("x27", 27, 0), + ("x28", 28, 0), + ("x29", 29, 0), + ("x30", 30, 0), + ("sp_elx", 31, 0), # SP + ("elr", 32, 0), # PC + ], + }, + "riscv": { + "architecture": "riscv:rv32", + "feature": "org.gnu.gdb.riscv:rv32", + "registers": [ + ("zero", 0, 0), + ("ra", 1, 0), + ("sp", 2, 0), + ("gp", 3, 0), + ("tp", 4, 0), + ("t0", 5, 0), + ("t1", 6, 0), + ("t2", 7, 0), + ("fp", 8, 0), + ("s1", 9, 0), + ("a0", 10, 0), + ("a1", 11, 0), + ("a2", 12, 0), + ("a3", 13, 0), + ("a4", 14, 0), + ("a5", 15, 0), + ("a6", 16, 0), + ("a7", 17, 0), + ("s2", 18, 0), + ("s3", 19, 0), + ("s4", 20, 0), + ("s5", 21, 0), + ("s6", 22, 0), + ("s7", 23, 0), + ("s8", 24, 0), + ("s9", 25, 0), + ("s10", 26, 0), + ("s11", 27, 0), + ("t3", 28, 0), + ("t4", 29, 0), + ("t5", 30, 0), + ("t6", 31, 0), + ("epc", 33, 0), + ], + }, + "x86-64": { + "architecture": "i386:x86-64", + "feature": "org.gnu.gdb.i386:x86-64", + "registers": [ + ("rax", 0, 0), + ("rbx", 1, 0), + ("rcx", 2, 0), + ("rdx", 3, 0), + ("rsi", 4, 0), + ("rdi", 5, 0), + ("rbp", 6, 0), + ("fsp", 7, 0), + ("r8", 8, 0), + ("r9", 9, 0), + ("r10", 10, 0), + ("r11", 11, 0), + ("r12", 12, 0), + ("r13", 13, 0), + ("r14", 14, 0), + ("r15", 15, 0), + ("rip", 16, 0), + ("rflags", 17, 0), + ("cs", 18, 0), + ("ss", 19, 0), + ("ds", 20, 0), + ("es", 21, 0), + ("fs", 22, 0), + ], + }, + "esp32s3": { + "architecture": "xtensa", # Use xtensa-esp32s3-elf-gdb + "feature": "", + "registers": [ + ("pc", 0, 0), + ("ps", 73, 292, 0x40000), # g_reg_offs placed it in the second position + ("a0", 1, 0), + ("a1", 2, 0), + ("a2", 3, 0), + ("a3", 4, 0), + ("a4", 5, 0), + ("a5", 6, 0), + ("a6", 7, 0), + ("a7", 8, 0), + ("a8", 9, 0), + ("a9", 10, 0), + ("a10", 11, 0), + ("a11", 12, 0), + ("a12", 13, 0), + ("a13", 14, 0), + ("a14", 15, 0), + ("a15", 16, 0), + ("windowbase", 69, 276, 0), + ("windowstart", 70, 280, 1), + ], + }, + "xtensa": { + "architecture": "xtensa", # Use xt-gdb + "feature": "", + "registers": [ + ("pc", 32, 0), + ("ps", 742, 472, 0x40000), + ("a0", 256, 4), + ("a1", 257, 0), + ("a2", 258, 0), + ("a3", 259, 0), + ("a4", 260, 0), + ("a5", 261, 0), + ("a6", 262, 0), + ("a7", 263, 0), + ("a8", 264, 0), + ("a9", 265, 0), + ("a10", 266, 0), + ("a11", 267, 0), + ("a12", 268, 0), + ("a13", 269, 0), + ("a14", 270, 0), + ("a15", 271, 0), + ("windowbase", 584, 308, 0), + ("windowstart", 585, 312, 1), + ], + }, +} + + +class RegInfo: + def __init__(self, name, size, tcb_offset=0): + self.name = name + self.size = size + self.tcb_offset = tcb_offset + + def __str__(self): + return f"{self.name}({self.size})" + + def __repr__(self): + return f"REG({self.name}, {self.size}, {self.tcb_offset})" + + +def get_reginfo(elf: LiefELF) -> List[RegInfo]: + # Now get register offset in TCB + _, data = elf.read_symbol("g_reg_offs") + reg_offs = Array(len(data) // 2, Int16ul).parse(data) + return [RegInfo("", elf.bits // 8, off) for off in reg_offs] + + +class Register: + def __init__( + self, name, regnum, size: int, offset=0, tcb_reg_off=0, value=0, fixedvalue=None + ): + self.name = name + self.regnum = regnum + self.size = size # size in bytes + self.offset = offset + self.tcb_reg_off = tcb_reg_off + self._value = value + self.fixedvalue = fixedvalue + self.logger = logging.getLogger(__name__) + + def __str__(self): + return f"{self.name}({self.regnum}, size:{self.size}, offset:{self.offset},{self.tcb_reg_off} value:{self.value:#x})" + + def __repr__(self): + return self.__str__() + + def __bytes__(self): + return self.value.to_bytes(self.size, "little", signed=self._value < 0) + + @property + def has_value(self): + return self._value is not None or self.fixedvalue is not None + + @property + def value(self): + return self._value if self.fixedvalue is None else self.fixedvalue + + @value.setter + def value(self, value): + """Set register value from bytes or value""" + if self.name == "": + return + + if isinstance(value, bytes) or isinstance(value, bytearray): + if len(value) != self.size: + raise ValueError( + f"Invalid value, expected {self.size} bytes, got {len(value)} bytes" + ) + self._value = int.from_bytes(bytes(value), "little") + elif isinstance(value, int): + self._value = value + else: + raise ValueError(f"Invalid value type: {type(value)}") + self.logger.debug(f"Set {self.name} = {self._value:#x}") + + +class Registers: + def __init__(self, elf, arch=None): + """ + Registers class to store register information + + :param arch: architecture name, or use current gdb architecture by default + """ + # if we don't have register names in elf, fallback to hardcoded register layouts + if not arch: + raise ValueError("Architecture is required to get register names") + + self.logger = logging.getLogger(__name__) + self.arch = arch + self._registers: List[Register] = [] + regsize = elf.get_pointer_size() + + reginfo = get_reginfo(elf) + layouts = g_reg_table.get(self.arch, {}).get("registers", []) + regoffsets = [r.tcb_offset for r in reginfo if r.tcb_offset != UINT16_MAX] + for i, (name, regnum, offset, *fixed) in enumerate(layouts): + register = Register( + name=name, + regnum=regnum, + size=regsize, + offset=offset, + tcb_reg_off=regoffsets[i] if i < len(regoffsets) else 0, + fixedvalue=fixed[0] if fixed else None, + ) + + self._registers.append(register) + self.logger.debug( + f"Register {name}({regnum}) offset: {offset}, tcb_off: {register.tcb_reg_off}" + ) + + self._registers.sort(key=lambda x: x.regnum) + + def __str__(self): + return f"({self.arch} x{len(self._registers)}, {self.sizeof()} bytes)" + + def __repr__(self): + return f"({self.arch} x{len(self._registers)}, {self.sizeof()} bytes)" + + def sizeof(self): + """Return total register size in byte""" + return sum(r.size for r in self._registers) + + def get(self, regnum: int = None, name: str = None) -> Register: + """Get register by register number""" + for reg in self._registers: + if reg.regnum == regnum: + return reg + + if reg.name == name: + return reg + + return None + + def set(self, value: Union[int, bytes], regnum: int = None, name: str = None): + """Set register value by register number""" + reg = self.get(regnum=regnum, name=name) + if not reg: + raise KeyError(f"Register {name or regnum} not found") + reg.value = value + + def load(self, xcpregs: bytes = None): + """ + Load register values from various sources. + + :param tcb: load register values from tcb.xcp.regs + :param address: load register values from specified address which points to regs in context + """ + + if xcpregs: + for reg in self._registers: + reg.value = xcpregs[reg.tcb_reg_off : reg.tcb_reg_off + reg.size] + else: + raise ValueError("No valid source to load register values") + + return self # allow to build and use Register().load() directly + + def to_g(self): + """Return GDB RSP g packet""" + reply = b"" + offset = 0 + for reg in self._registers: + if reg.offset and reg.offset != offset: + reply += b"xx" * (reg.offset - offset) + + if not reg.has_value: + reply += b"xx" * reg.size + else: + reply += hexlify(bytes(reg)) + + offset += reg.offset + reg.size + return reply + + def from_g(self, data: bytes): + """Parse GDB RSP G packet""" + offset = 0 + for reg in self._registers: + offset = reg.offset if reg.offset else offset + self.logger.debug( + f"Parse {reg.name}({reg.regnum}) from {offset}, data: {data[offset:offset+reg.size]}" + ) + reg.value = data[offset : offset + reg.size] + offset += reg.size + + def __iter__(self): + return iter(self._registers) + + def __len__(self): + return len(self._registers) + + def __getitem__(self, key): + return self._registers[key] diff --git a/tools/pynuttx/nxstub/__init__.py b/tools/pynuttx/nxstub/__init__.py index b5455b34c44..ce0a7c227af 100644 --- a/tools/pynuttx/nxstub/__init__.py +++ b/tools/pynuttx/nxstub/__init__.py @@ -29,10 +29,11 @@ import subprocess import traceback from typing import List +from nxreg.register import Registers, g_reg_table + from . import utils from .gdbstub import GDBStub, Target from .proxy import TargetProxy -from .registers import Registers, g_reg_table from .target import RawMemory # Default GDB init command, note it should start with a space diff --git a/tools/pynuttx/nxstub/registers.py b/tools/pynuttx/nxstub/registers.py index f7c9f8485fc..94c6f733370 100644 --- a/tools/pynuttx/nxstub/registers.py +++ b/tools/pynuttx/nxstub/registers.py @@ -19,392 +19,3 @@ # under the License. # ############################################################################ - -import logging -from binascii import hexlify -from typing import List, Union - -from . import utils - -UINT16_MAX = 0xFFFF - -# GDB default register information for different architectures -# -# Format: ("reg-name", regnum, g/G offset, fixed-value(optional)) -# -# To get the default register offset in g/G packet, using GDB command: -# (gdb) set architecture (e.g. set architecture arm), leave empty to see all supported architectures -# (gdb) maint print remote-registers - -g_reg_table = { - "arm": { - "architecture": "arm", - "feature": "org.gnu.gdb.arm.m-profile", - "registers": [ - ("r0", 0, 0), - ("r1", 1, 0), - ("r2", 2, 0), - ("r3", 3, 0), - ("r4", 4, 0), - ("r5", 5, 0), - ("r6", 6, 0), - ("fp", 7, 0), - ("r8", 8, 0), - ("sb", 9, 0), - ("sl", 10, 0), - ("r11", 11, 0), - ("ip", 12, 0), - ("sp", 13, 0), - ("lr", 14, 0), - ("pc", 15, 0), - ("xpsr", 16, 0), - ], - }, - "arm-a": { - "architecture": "arm", - "feature": "org.gnu.gdb.arm", - "registers": [ - ("r0", 0, 0), - ("r1", 1, 0), - ("r2", 2, 0), - ("r3", 3, 0), - ("r4", 4, 0), - ("r5", 5, 0), - ("r6", 6, 0), - ("fp", 7, 0), - ("r8", 8, 0), - ("sb", 9, 0), - ("sl", 10, 0), - ("r11", 11, 0), - ("ip", 12, 0), - ("sp", 13, 0), - ("lr", 14, 0), - ("pc", 15, 0), - ("cpsr", 25, 164), - ], - }, - "arm64": { - "architecture": "aarch64", - "feature": "org.gnu.gdb.aarch64", - "registers": [ - ("x0", 0, 0), - ("x1", 1, 0), - ("x2", 2, 0), - ("x3", 3, 0), - ("x4", 4, 0), - ("x5", 5, 0), - ("x6", 6, 0), - ("x7", 7, 0), - ("x8", 8, 0), - ("x9", 9, 0), - ("x10", 10, 0), - ("x11", 11, 0), - ("x12", 12, 0), - ("x13", 13, 0), - ("x14", 14, 0), - ("x15", 15, 0), - ("x16", 16, 0), - ("x17", 17, 0), - ("x18", 18, 0), - ("x19", 19, 0), - ("x20", 20, 0), - ("x21", 21, 0), - ("x22", 22, 0), - ("x23", 23, 0), - ("x24", 24, 0), - ("x25", 25, 0), - ("x26", 26, 0), - ("x27", 27, 0), - ("x28", 28, 0), - ("x29", 29, 0), - ("x30", 30, 0), - ("sp_elx", 31, 0), # SP - ("elr", 32, 0), # PC - ], - }, - "riscv": { - "architecture": "riscv:rv32", - "feature": "org.gnu.gdb.riscv:rv32", - "registers": [ - ("zero", 0, 0), - ("ra", 1, 0), - ("sp", 2, 0), - ("gp", 3, 0), - ("tp", 4, 0), - ("t0", 5, 0), - ("t1", 6, 0), - ("t2", 7, 0), - ("fp", 8, 0), - ("s1", 9, 0), - ("a0", 10, 0), - ("a1", 11, 0), - ("a2", 12, 0), - ("a3", 13, 0), - ("a4", 14, 0), - ("a5", 15, 0), - ("a6", 16, 0), - ("a7", 17, 0), - ("s2", 18, 0), - ("s3", 19, 0), - ("s4", 20, 0), - ("s5", 21, 0), - ("s6", 22, 0), - ("s7", 23, 0), - ("s8", 24, 0), - ("s9", 25, 0), - ("s10", 26, 0), - ("s11", 27, 0), - ("t3", 28, 0), - ("t4", 29, 0), - ("t5", 30, 0), - ("t6", 31, 0), - ("epc", 33, 0), - ], - }, - "x86-64": { - "architecture": "i386:x86-64", - "feature": "org.gnu.gdb.i386:x86-64", - "registers": [ - ("rax", 0, 0), - ("rbx", 1, 0), - ("rcx", 2, 0), - ("rdx", 3, 0), - ("rsi", 4, 0), - ("rdi", 5, 0), - ("rbp", 6, 0), - ("fsp", 7, 0), - ("r8", 8, 0), - ("r9", 9, 0), - ("r10", 10, 0), - ("r11", 11, 0), - ("r12", 12, 0), - ("r13", 13, 0), - ("r14", 14, 0), - ("r15", 15, 0), - ("rip", 16, 0), - ("rflags", 17, 0), - ("cs", 18, 0), - ("ss", 19, 0), - ("ds", 20, 0), - ("es", 21, 0), - ("fs", 22, 0), - ], - }, - "esp32s3": { - "architecture": "xtensa", # Use xtensa-esp32s3-elf-gdb - "feature": "", - "registers": [ - ("pc", 0, 0), - ("ps", 73, 292, 0x40000), # g_reg_offs placed it in the second position - ("a0", 1, 0), - ("a1", 2, 0), - ("a2", 3, 0), - ("a3", 4, 0), - ("a4", 5, 0), - ("a5", 6, 0), - ("a6", 7, 0), - ("a7", 8, 0), - ("a8", 9, 0), - ("a9", 10, 0), - ("a10", 11, 0), - ("a11", 12, 0), - ("a12", 13, 0), - ("a13", 14, 0), - ("a14", 15, 0), - ("a15", 16, 0), - ("windowbase", 69, 276, 0), - ("windowstart", 70, 280, 1), - ], - }, - "xtensa": { - "architecture": "xtensa", # Use xt-gdb - "feature": "", - "registers": [ - ("pc", 32, 0), - ("ps", 742, 472, 0x40000), - ("a0", 256, 4), - ("a1", 257, 0), - ("a2", 258, 0), - ("a3", 259, 0), - ("a4", 260, 0), - ("a5", 261, 0), - ("a6", 262, 0), - ("a7", 263, 0), - ("a8", 264, 0), - ("a9", 265, 0), - ("a10", 266, 0), - ("a11", 267, 0), - ("a12", 268, 0), - ("a13", 269, 0), - ("a14", 270, 0), - ("a15", 271, 0), - ("windowbase", 584, 308, 0), - ("windowstart", 585, 312, 1), - ], - }, -} - - -class Register: - def __init__( - self, name, regnum, size: int, offset=0, tcb_reg_off=0, value=0, fixedvalue=None - ): - self.name = name - self.regnum = regnum - self.size = size # size in bytes - self.offset = offset - self.tcb_reg_off = tcb_reg_off - self._value = value - self.fixedvalue = fixedvalue - self.logger = logging.getLogger(__name__) - - def __str__(self): - return f"{self.name}({self.regnum}, size:{self.size}, offset:{self.offset},{self.tcb_reg_off} value:{self.value:#x})" - - def __repr__(self): - return self.__str__() - - def __bytes__(self): - return self.value.to_bytes(self.size, "little", signed=self._value < 0) - - @property - def has_value(self): - return self._value is not None or self.fixedvalue is not None - - @property - def value(self): - return self._value if self.fixedvalue is None else self.fixedvalue - - @value.setter - def value(self, value): - """Set register value from bytes or value""" - if self.name == "": - return - - if isinstance(value, bytes) or isinstance(value, bytearray): - if len(value) != self.size: - raise ValueError( - f"Invalid value, expected {self.size} bytes, got {len(value)} bytes" - ) - self._value = int.from_bytes(bytes(value), "little") - elif isinstance(value, int): - self._value = value - else: - raise ValueError(f"Invalid value type: {type(value)}") - self.logger.debug(f"Set {self.name} = {self._value:#x}") - - -class Registers: - def __init__(self, elf, arch=None): - """ - Registers class to store register information - - :param arch: architecture name, or use current gdb architecture by default - """ - # if we don't have register names in elf, fallback to hardcoded register layouts - if not arch: - raise ValueError("Architecture is required to get register names") - - self.logger = logging.getLogger(__name__) - self.arch = arch - self._registers: List[Register] = [] - regsize = elf.get_pointer_size() - reginfo = utils.get_reginfo(elf) - layouts = g_reg_table.get(self.arch, {}).get("registers", []) - regoffsets = [r.tcb_offset for r in reginfo if r.tcb_offset != UINT16_MAX] - for i, (name, regnum, offset, *fixed) in enumerate(layouts): - register = Register( - name=name, - regnum=regnum, - size=regsize, - offset=offset, - tcb_reg_off=regoffsets[i] if i < len(regoffsets) else 0, - fixedvalue=fixed[0] if fixed else None, - ) - - self._registers.append(register) - self.logger.debug( - f"Register {name}({regnum}) offset: {offset}, tcb_off: {register.tcb_reg_off}" - ) - - self._registers.sort(key=lambda x: x.regnum) - - def __str__(self): - return f"({self.arch} x{len(self._registers)}, {self.sizeof()} bytes)" - - def __repr__(self): - return f"({self.arch} x{len(self._registers)}, {self.sizeof()} bytes)" - - def sizeof(self): - """Return total register size in byte""" - return sum(r.size for r in self._registers) - - def get(self, regnum: int = None, name: str = None) -> Register: - """Get register by register number""" - for reg in self._registers: - if reg.regnum == regnum: - return reg - - if reg.name == name: - return reg - - return None - - def set(self, value: Union[int, bytes], regnum: int = None, name: str = None): - """Set register value by register number""" - reg = self.get(regnum=regnum, name=name) - if not reg: - raise KeyError(f"Register {name or regnum} not found") - reg.value = value - - def load(self, xcpregs: bytes = None): - """ - Load register values from various sources. - - :param tcb: load register values from tcb.xcp.regs - :param address: load register values from specified address which points to regs in context - """ - - if xcpregs: - for reg in self._registers: - reg.value = xcpregs[reg.tcb_reg_off : reg.tcb_reg_off + reg.size] - else: - raise ValueError("No valid source to load register values") - - return self # allow to build and use Register().load() directly - - def to_g(self): - """Return GDB RSP g packet""" - reply = b"" - offset = 0 - for reg in self._registers: - if reg.offset and reg.offset != offset: - reply += b"xx" * (reg.offset - offset) - - if not reg.has_value: - reply += b"xx" * reg.size - else: - reply += hexlify(bytes(reg)) - - offset += reg.offset + reg.size - return reply - - def from_g(self, data: bytes): - """Parse GDB RSP G packet""" - offset = 0 - for reg in self._registers: - offset = reg.offset if reg.offset else offset - self.logger.debug( - f"Parse {reg.name}({reg.regnum}) from {offset}, data: {data[offset:offset+reg.size]}" - ) - reg.value = data[offset : offset + reg.size] - offset += reg.size - - def __iter__(self): - return iter(self._registers) - - def __len__(self): - return len(self._registers) - - def __getitem__(self, key): - return self._registers[key] diff --git a/tools/pynuttx/nxstub/target.py b/tools/pynuttx/nxstub/target.py index ed5116d752f..7b07daa5f00 100644 --- a/tools/pynuttx/nxstub/target.py +++ b/tools/pynuttx/nxstub/target.py @@ -24,8 +24,9 @@ import logging import traceback from typing import List +from nxreg.register import Registers + from . import utils -from .registers import Registers class RawMemory: diff --git a/tools/pynuttx/nxstub/utils.py b/tools/pynuttx/nxstub/utils.py index aa537c8bae4..8c9f57cba3c 100644 --- a/tools/pynuttx/nxstub/utils.py +++ b/tools/pynuttx/nxstub/utils.py @@ -43,19 +43,6 @@ def get_regsize(elf: LiefELF) -> int: return sym.size // get_ncpus(elf) -class RegInfo: - def __init__(self, name, size, tcb_offset=0): - self.name = name - self.size = size - self.tcb_offset = tcb_offset - - def __str__(self): - return f"{self.name}({self.size})" - - def __repr__(self): - return f"REG({self.name}, {self.size}, {self.tcb_offset})" - - def get_tcbinfo(elf: LiefELF): tcbinfo_s = Struct( "pid_off" / Int16ul, # FIXME: only little endian supported @@ -81,13 +68,6 @@ def get_tcb_size(elf: LiefELF) -> int: return g_idletcb.size // ncpus -def get_reginfo(elf: LiefELF) -> List[RegInfo]: - # Now get register offset in TCB - _, data = elf.read_symbol("g_reg_offs") - reg_offs = Array(len(data) // 2, Int16ul).parse(data) - return [RegInfo("", elf.bits // 8, off) for off in reg_offs] - - def parse_array(data, type_, narray): return Array(narray, type_).parse(data) -- Gitee From 0565401e6a56c40c118dfab333f2469ec78d52fb Mon Sep 17 00:00:00 2001 From: yangao1 Date: Tue, 18 Feb 2025 20:52:47 +0800 Subject: [PATCH 094/235] pynuttx/tools/nxreg/register.py: modify get_reginfo function VELAPLATFO-54008 read_symbol from g_reginfo,add return reg.offsets Change-Id: I37bed1ecad517b7846dd2407ad486652a01bf8d4 Signed-off-by: yangao1 --- tools/pynuttx/nxreg/register.py | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/tools/pynuttx/nxreg/register.py b/tools/pynuttx/nxreg/register.py index e5525703fe2..dbadc4053fb 100644 --- a/tools/pynuttx/nxreg/register.py +++ b/tools/pynuttx/nxreg/register.py @@ -22,7 +22,7 @@ import logging from binascii import hexlify from typing import List, Union -from construct import Array, Int16ul +from construct import Array, Int8ul, Int16ul, PaddedString, Struct from nxelf.elf import LiefELF UINT16_MAX = 0xFFFF @@ -251,9 +251,20 @@ class RegInfo: def get_reginfo(elf: LiefELF) -> List[RegInfo]: # Now get register offset in TCB - _, data = elf.read_symbol("g_reg_offs") - reg_offs = Array(len(data) // 2, Int16ul).parse(data) - return [RegInfo("", elf.bits // 8, off) for off in reg_offs] + _, data = elf.read_symbol("g_reginfo") + + reginfo_s = Struct( + "name" / PaddedString(8, "utf-8"), + "size" / Int8ul, + "regnum" / Int8ul, + "toffset" / Int16ul, + "goffset" / Int16ul, + ) + + regsnum = len(data) // reginfo_s.sizeof() + reginfo_t = Array(regsnum, reginfo_s) + reginfo = reginfo_t.parse(data) + return [RegInfo("", elf.bits // 8, reg.toffset) for reg in reginfo] class Register: -- Gitee From d76daacdccb27b1ea7638ee9e6d6f5ea788d54a1 Mon Sep 17 00:00:00 2001 From: yangao1 Date: Tue, 18 Feb 2025 20:39:24 +0800 Subject: [PATCH 095/235] pynuttx/nxreg/register.py:revise register name for arch VELAPLATFO-54008 Change-Id: I1ee3625be44623be9bce869f83d8e5ee62c13bdd Signed-off-by: yangao1 --- tools/pynuttx/nxreg/register.py | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/tools/pynuttx/nxreg/register.py b/tools/pynuttx/nxreg/register.py index dbadc4053fb..d85771e6153 100644 --- a/tools/pynuttx/nxreg/register.py +++ b/tools/pynuttx/nxreg/register.py @@ -39,12 +39,12 @@ g_reg_table = { ("r4", 4, 0), ("r5", 5, 0), ("r6", 6, 0), - ("fp", 7, 0), + ("r7", 7, 0), ("r8", 8, 0), - ("sb", 9, 0), - ("sl", 10, 0), + ("r9", 9, 0), + ("r10", 10, 0), ("r11", 11, 0), - ("ip", 12, 0), + ("r12", 12, 0), ("sp", 13, 0), ("lr", 14, 0), ("pc", 15, 0), @@ -62,12 +62,12 @@ g_reg_table = { ("r4", 4, 0), ("r5", 5, 0), ("r6", 6, 0), - ("fp", 7, 0), + ("r7", 7, 0), ("r8", 8, 0), - ("sb", 9, 0), - ("sl", 10, 0), + ("r9", 9, 0), + ("r10", 10, 0), ("r11", 11, 0), - ("ip", 12, 0), + ("r12", 12, 0), ("sp", 13, 0), ("lr", 14, 0), ("pc", 15, 0), -- Gitee From 56e4648c0f3ccf9a05e35cd106e5f781fa05c7af Mon Sep 17 00:00:00 2001 From: yangao1 Date: Thu, 20 Feb 2025 22:12:43 +0800 Subject: [PATCH 096/235] tools/pynuttx:modify framework to handle register in nxreg VELAPLATFO-57109 Change-Id: Id1d0ff948d4c14d3d0ae7faf15df5692fb56fa45 Signed-off-by: yangao1 (cherry picked from commit fff4792197e2c8c30cc0d69330dce9d38b4128cf) --- tools/pynuttx/nxgdb/thread.py | 75 +++++++++++++++++---------------- tools/pynuttx/nxreg/register.py | 52 ++++++++++++++++------- tools/pynuttx/nxstub/target.py | 17 ++++---- 3 files changed, 83 insertions(+), 61 deletions(-) diff --git a/tools/pynuttx/nxgdb/thread.py b/tools/pynuttx/nxgdb/thread.py index f4bf4edebce..6bba7d90d26 100644 --- a/tools/pynuttx/nxgdb/thread.py +++ b/tools/pynuttx/nxgdb/thread.py @@ -22,8 +22,11 @@ import argparse from enum import Enum, auto +from typing import Union import gdb +from nxelf.elf import LiefELF +from nxreg.register import Registers, g_reg_table from . import utils from .stack import Stack @@ -40,38 +43,36 @@ def is_thread_command_supported(): return len(gdb.selected_inferior().threads()) > CONFIG_SMP_NCPUS -class Registers: +class NxRegisters: saved_regs = None - reginfo = None def __init__(self): - if not Registers.reginfo: - reginfo = {} - - tcb_info = utils.parse_and_eval("g_tcbinfo") - reg_info = tcb_info.u.reginfo - reginfo = { - str(reg.name.string()): { - "rmt_nr": int(reg.regnum), - "tcb_reg_off": int(reg.toffset), - } - for reg in utils.ArrayIterator(reg_info, tcb_info.regs_num) - } - - Registers.reginfo = reginfo - - def load(self, regs): - """Load registers from context register address""" - regs = int(regs) - for name, info in Registers.reginfo.items(): - addr = regs + info["tcb_reg_off"] - # value = *(uintptr_t *)addr - value = ( - gdb.Value(addr) - .cast(utils.lookup_type("uintptr_t").pointer()) - .dereference() + elf = gdb.objfiles()[0] + elf = LiefELF(elf.filename) + + def read_memory(addr, size): + return bytes(gdb.selected_inferior().read_memory(addr, size)) + + arch = gdb.selected_inferior().architecture() + mapped_arch_name = self.map_gdbarch_name(arch.name()) + if mapped_arch_name not in g_reg_table: + raise ValueError( + f"Architecture {mapped_arch_name} is not found in g_reg_table.\n" ) - gdb.execute(f"set ${name}={int(value)}") + + self.registers = Registers(elf, arch=mapped_arch_name, readmem=read_memory) + + def map_gdbarch_name(self, arch: str): + for arch_key, arch_info in g_reg_table.items(): + if arch in arch_info["architecture"]: + return arch_key + return None + + def load(self, regs: Union[int, gdb.Value] = None): + """Load registers from context register address""" + self.registers.load(regs) + for reg in self.registers: + gdb.execute(f"set ${reg.name} = {reg.value}") def switch(self, pid): """Switch to the specified thread""" @@ -93,29 +94,29 @@ class Registers: def save(self): """Save current registers""" - if Registers.saved_regs: + if NxRegisters.saved_regs: # Already saved return registers = {} frame = gdb.newest_frame() - for name, _ in Registers.reginfo.items(): - value = frame.read_register(name) - registers[name] = value + for reg in self.registers: + value = frame.read_register(reg.name) + registers[reg.name] = value - Registers.saved_regs = registers + NxRegisters.saved_regs = registers def restore(self): - if not Registers.saved_regs: + if not NxRegisters.saved_regs: return - for name, value in Registers.saved_regs.items(): + for name, value in NxRegisters.saved_regs.items(): gdb.execute(f"set ${name}={int(value)}") - Registers.saved_regs = None + NxRegisters.saved_regs = None -g_registers = Registers() +g_registers = NxRegisters() class SetRegs(gdb.Command): diff --git a/tools/pynuttx/nxreg/register.py b/tools/pynuttx/nxreg/register.py index d85771e6153..2d42927237e 100644 --- a/tools/pynuttx/nxreg/register.py +++ b/tools/pynuttx/nxreg/register.py @@ -29,7 +29,16 @@ UINT16_MAX = 0xFFFF g_reg_table = { "arm": { - "architecture": "arm", + "architecture": [ + "arm", + "armv6-m", + "armv6s-m", + "armv7e-m", + "armv8-m", + "armv8-m.base", + "armv8-m.main", + "armv8.1-m.main", + ], "feature": "org.gnu.gdb.arm.m-profile", "registers": [ ("r0", 0, 0), @@ -48,11 +57,11 @@ g_reg_table = { ("sp", 13, 0), ("lr", 14, 0), ("pc", 15, 0), - ("xpsr", 16, 0), + ("xpsr", 25, 0), ], }, "arm-a": { - "architecture": "arm", + "architecture": ["armv6", "armv7", "armv8-a", "armv8-r", "armv9-a"], "feature": "org.gnu.gdb.arm", "registers": [ ("r0", 0, 0), @@ -75,7 +84,7 @@ g_reg_table = { ], }, "arm64": { - "architecture": "aarch64", + "architecture": ["aarch64", "aarch64:ilp32", "aarch64:armv8-r"], "feature": "org.gnu.gdb.aarch64", "registers": [ ("x0", 0, 0), @@ -114,7 +123,7 @@ g_reg_table = { ], }, "riscv": { - "architecture": "riscv:rv32", + "architecture": ["riscv", "riscv:rv32", "riscv:rv64"], "feature": "org.gnu.gdb.riscv:rv32", "registers": [ ("zero", 0, 0), @@ -149,11 +158,11 @@ g_reg_table = { ("t4", 29, 0), ("t5", 30, 0), ("t6", 31, 0), - ("epc", 33, 0), + ("epc", 33, 0), # PC ], }, "x86-64": { - "architecture": "i386:x86-64", + "architecture": ["i386", "i386:x86-64", "i386:x86-64:intel", "i386:intel"], "feature": "org.gnu.gdb.i386:x86-64", "registers": [ ("rax", 0, 0), @@ -182,7 +191,7 @@ g_reg_table = { ], }, "esp32s3": { - "architecture": "xtensa", # Use xtensa-esp32s3-elf-gdb + "architecture": ["esp32s3"], # Use xtensa-esp32s3-elf-gdb "feature": "", "registers": [ ("pc", 0, 0), @@ -208,7 +217,7 @@ g_reg_table = { ], }, "xtensa": { - "architecture": "xtensa", # Use xt-gdb + "architecture": ["xtensa"], # Use xt-gdb "feature": "", "registers": [ ("pc", 32, 0), @@ -264,7 +273,8 @@ def get_reginfo(elf: LiefELF) -> List[RegInfo]: regsnum = len(data) // reginfo_s.sizeof() reginfo_t = Array(regsnum, reginfo_s) reginfo = reginfo_t.parse(data) - return [RegInfo("", elf.bits // 8, reg.toffset) for reg in reginfo] + + return [RegInfo(reg.name, elf.bits // 8, reg.toffset) for reg in reginfo] class Register: @@ -316,12 +326,14 @@ class Register: self.logger.debug(f"Set {self.name} = {self._value:#x}") -class Registers: - def __init__(self, elf, arch=None): +class GeneralRegisters: + def __init__(self, elf, arch=None, readmem=None): """ Registers class to store register information + :param elf: Parsed ELF file :param arch: architecture name, or use current gdb architecture by default + :param readmem: function to read memory """ # if we don't have register names in elf, fallback to hardcoded register layouts if not arch: @@ -329,6 +341,7 @@ class Registers: self.logger = logging.getLogger(__name__) self.arch = arch + self.readmem = readmem self._registers: List[Register] = [] regsize = elf.get_pointer_size() @@ -351,6 +364,8 @@ class Registers: ) self._registers.sort(key=lambda x: x.regnum) + ncpu = elf.get_symbol("g_running_tasks").size // elf.get_pointer_size() + self.xcp_reg_size = elf.get_symbol("g_last_regs").size // ncpu def __str__(self): return f"({self.arch} x{len(self._registers)}, {self.sizeof()} bytes)" @@ -380,7 +395,7 @@ class Registers: raise KeyError(f"Register {name or regnum} not found") reg.value = value - def load(self, xcpregs: bytes = None): + def load(self, addr: int): """ Load register values from various sources. @@ -388,12 +403,15 @@ class Registers: :param address: load register values from specified address which points to regs in context """ + if self.readmem is None: + raise ValueError("readmem is not set") + + xcpregs = self.readmem(addr, self.xcp_reg_size) if xcpregs: for reg in self._registers: reg.value = xcpregs[reg.tcb_reg_off : reg.tcb_reg_off + reg.size] else: - raise ValueError("No valid source to load register values") - + raise ValueError("No valid source to load register values.\n") return self # allow to build and use Register().load() directly def to_g(self): @@ -431,3 +449,7 @@ class Registers: def __getitem__(self, key): return self._registers[key] + + +def Registers(elf, arch=None, readmem=None) -> GeneralRegisters: + return GeneralRegisters(elf, arch, readmem) diff --git a/tools/pynuttx/nxstub/target.py b/tools/pynuttx/nxstub/target.py index 7b07daa5f00..c1723630793 100644 --- a/tools/pynuttx/nxstub/target.py +++ b/tools/pynuttx/nxstub/target.py @@ -141,12 +141,10 @@ class Target: g_running_tasks = utils.parse_array(data, pointer, ncpus) self.logger.debug(f"g_running_tasks: {g_running_tasks}@{sym.value:#x}") - data, _ = self._read_symbol("g_last_regs") # an array of uintptr_t - assert len(data) % regsize == 0 - g_last_regs = [data[i * regsize : (i + 1) * regsize] for i in range(ncpus)] - def parse_tcb(address: int) -> ThreadInfo: - registers = Registers(self.elf, arch=self.arch) + registers = Registers( + self.elf, arch=self.arch, readmem=self.memory_read + ) data = self.memory_read(address, tcbsize) if not data or len(data) != tcbsize: self.logger.error(f"Invalid TCB size: {len(data)} != {tcbsize}") @@ -165,15 +163,16 @@ class Target: if address in g_running_tasks: # Running task registers is not in memory, best chance is the registers # stored in g_last_regs when assert happened. - xcpregs = g_last_regs[g_running_tasks.index(address)] + g_last_regs = self.elf.get_symbol("g_last_regs").value + cpu = g_running_tasks.index(address) + xcpregs = cpu * regsize + g_last_regs else: off = tcbinfo.regs_off xcpregs = data[off : off + pointer.sizeof()] xcpregs = pointer.parse(xcpregs) - xcpregs = self.memory_read(xcpregs, regsize) try: - registers.load(xcpregs=xcpregs) + registers.load(addr=xcpregs) except ValueError as e: self.logger.error(f"Failed to load registers: {e}") @@ -299,7 +298,7 @@ class Target: # try if it's a symbol, note that expression is not supported. address = self.elf.get_symbol(address).value - self.registers.load(self.memory_read(address, utils.get_regsize(self.elf))) + self.registers.load(address) return f"Loaded registers from {address:#x}\n" elif command.startswith(b"help"): return ( -- Gitee From 1c42124bc933c22a2e187bb8116f908c86c80295 Mon Sep 17 00:00:00 2001 From: yangao1 Date: Tue, 11 Mar 2025 11:31:51 +0800 Subject: [PATCH 097/235] tools/pynuttx:remote g_prefix from all local variables VELAPLATFO-57109 Change-Id: Ie23d3735f7cc4b2173bb16ecd733bf752870df9a Signed-off-by: yangao1 (cherry picked from commit 3eea2a7cc3a94712b452646d70a0e79107095ed2) --- tools/pynuttx/nxgdb/kasan.py | 193 ++++++++++++++++++++++++++++++++ tools/pynuttx/nxgdb/net.py | 4 +- tools/pynuttx/nxgdb/notesnap.py | 94 ++++++++++++++++ tools/pynuttx/nxgdb/pm.py | 103 +++++++++++++++++ tools/pynuttx/nxgdb/utils.py | 6 +- tools/pynuttx/nxstub/target.py | 30 ++--- tools/pynuttx/nxstub/utils.py | 8 +- 7 files changed, 414 insertions(+), 24 deletions(-) create mode 100644 tools/pynuttx/nxgdb/kasan.py create mode 100644 tools/pynuttx/nxgdb/notesnap.py create mode 100644 tools/pynuttx/nxgdb/pm.py diff --git a/tools/pynuttx/nxgdb/kasan.py b/tools/pynuttx/nxgdb/kasan.py new file mode 100644 index 00000000000..c45c1571ed0 --- /dev/null +++ b/tools/pynuttx/nxgdb/kasan.py @@ -0,0 +1,193 @@ +############################################################################ +# tools/pynuttx/nxgdb/kasan.py +# +# SPDX-License-Identifier: Apache-2.0 +# +# Licensed to the Apache Software Foundation (ASF) under one or more +# contributor license agreements. See the NOTICE file distributed with +# this work for additional information regarding copyright ownership. The +# ASF licenses this file to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance with the +# License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# +############################################################################ + +import argparse +import itertools + +import gdb + +from . import utils + + +class KASanGeneric: + def __init__(self, scope, begin, end, shadow, bitwidth, scale, shift=0): + self.scope = scope + self.begin = int(begin) + self.end = int(end) + self.shadow = shadow + self.bitwidth = int(bitwidth) + self.scale = int(scale) + self.shift = int(shift) + + def check_addr(self, addr): + return self.get_allocation_tag(addr) + + def contains(self, addr): + return self.begin <= self.untag_addr(addr) <= self.end + + def get_allocation_tag(self, addr): + distance = (addr - self.begin) // self.scale + index = distance // self.bitwidth + bit = distance % self.bitwidth + return True if self.shadow[index] >> bit & 0x01 else False + + def get_logical_tag(self, addr): + return int(addr >> self.shift) + + def untag_addr(self, addr): + return addr + + +class KASanSwtags(KASanGeneric): + def check_addr(self, addr): + return self.get_allocation_tag(addr) != self.get_logical_tag(addr) + + def get_allocation_tag(self, addr): + untag_addr = self.untag_addr(addr) + distance = untag_addr - self.begin + index = distance // self.scale + return self.shadow[index] + + def untag_addr(self, addr): + return addr & ~(0xFF << self.shift) + + +command_actions = { + "check": lambda addr, region: print( + f"[{region.scope}] Addr 0x{addr:X} is {'invalid' if region.check_addr(addr) else 'valid'}" + ), + "print-allocation-tag": lambda addr, region: print( + f"[{region.scope}] Addr 0x{addr:X} allocation tag is: 0x{region.get_allocation_tag(addr):X}" + ), + "print-logical-tag": lambda addr, region: print( + f"[{region.scope}] Addr 0x{addr:X} logical tag is: 0x{region.get_logical_tag(addr):X}" + ), +} + + +class KASan(gdb.Command): + + def __init__(self): + if utils.get_symbol_value("CONFIG_MM_KASAN") is None: + return + + super().__init__("kasan", gdb.COMMAND_USER) + + """ Common bit width and kasan alignment length in multiple modes """ + bitwidth = utils.sizeof("long") * 8 + scale = utils.get_symbol_value("KASAN_SHADOW_SCALE") + + """ Get the array of KASan regions """ + region_count = utils.parse_and_eval("g_region_count") + region = utils.parse_and_eval("g_region") + + self.regions: list[KASanGeneric] = [] + if utils.get_symbol_value("CONFIG_MM_KASAN_GENERIC") is not None: + print("KASan Mode: Generic") + for region in utils.ArrayIterator(region, region_count): + self.regions.append( + KASanGeneric( + "Heap", + region["begin"], + region["end"], + region["shadow"], + bitwidth, + scale, + ) + ) + + if utils.get_symbol_value("CONFIG_MM_KASAN_SW_TAGS") is not None: + print("KASan Mode: Softtags") + shift = utils.get_symbol_value("KASAN_TAG_SHIFT") + for region in utils.ArrayIterator(region, region_count): + self.regions.append( + KASanSwtags( + "Heap", + region["begin"], + region["end"], + region["shadow"], + bitwidth, + scale, + shift, + ) + ) + + if utils.get_symbol_value("CONFIG_MM_KASAN_GLOBAL") is not None: + print("KASan Support Checking Global Variables") + scale = utils.get_symbol_value("CONFIG_MM_KASAN_GLOBAL_ALIGN") + global_region = utils.parse_and_eval("g_global_region") + for index in itertools.count(0): + if global_region[index] == 0: + break + region = global_region[index].dereference() + self.regions.append( + KASanGeneric( + "Globals", + region["begin"], + region["end"], + region["shadow"], + bitwidth, + scale, + ) + ) + + def invoke(self, args, from_tty): + parser = argparse.ArgumentParser( + description="Memory Tagging Commands", add_help=False + ) + subparsers = parser.add_subparsers(dest="command") + subparsers.add_parser( + "check", + help="Validate a pointer's logical tag against the allocation tag.", + ) + subparsers.add_parser( + "print-allocation-tag", help="Print the allocation tag for ADDRESS." + ) + subparsers.add_parser( + "print-logical-tag", help="Print the logical tag from POINTER." + ) + + try: + parsed_args, addresses = parser.parse_known_args(args.split()) + except SystemExit: + print(parser.format_help()) + return + + if not parsed_args.command: + print(parser.format_help()) + return + + regions = {} + for addr in addresses: + addr = utils.parse_arg(addr) + for region in self.regions: + if region.contains(addr): + regions[addr] = region + break + else: + print(f"Addr 0x{addr:X} Not in any region") + + if parsed_args.command in command_actions: + for addr, region in regions.items(): + command_actions[parsed_args.command](addr, region) + else: + print(f"Unknown command: {parsed_args.command}") diff --git a/tools/pynuttx/nxgdb/net.py b/tools/pynuttx/nxgdb/net.py index e4a95c1614c..d0320476822 100644 --- a/tools/pynuttx/nxgdb/net.py +++ b/tools/pynuttx/nxgdb/net.py @@ -76,8 +76,8 @@ def socket_for_each_entry(proto): readahead = conn["readahead"] """ - g_active_connections = gdb.parse_and_eval("g_active_%s_connections" % proto) - for node in NxDQueue(g_active_connections, "struct socket_conn_s", "node"): + active_connections = gdb.parse_and_eval("g_active_%s_connections" % proto) + for node in NxDQueue(active_connections, "struct socket_conn_s", "node"): # udp_conn_s::socket_conn_s sconn yield utils.container_of( node, diff --git a/tools/pynuttx/nxgdb/notesnap.py b/tools/pynuttx/nxgdb/notesnap.py new file mode 100644 index 00000000000..ed38f0c3d5d --- /dev/null +++ b/tools/pynuttx/nxgdb/notesnap.py @@ -0,0 +1,94 @@ +############################################################################ +# tools/pynuttx/nxgdb/notesnap.py +# +# Licensed to the Apache Software Foundation (ASF) under one or more +# contributor license agreements. See the NOTICE file distributed with +# this work for additional information regarding copyright ownership. The +# ASF licenses this file to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance with the +# License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# +############################################################################ + +import gdb + +from . import utils + +CONFIG_SMP = utils.has_field("struct notesnap_chunk_s", "cpu") +CONFIG_DRIVERS_NOTESNAP_NBUFFERS = utils.get_field_nitems("struct notesnap_s", "buffer") + + +class NoteSnapChunk: + def __init__(self, notetype, pid, args, cpu=0): + self.notetype = notetype + self.pid = pid + self.args = args + self.cpu = cpu + + @property + def taskname(self): + return utils.get_task_name(utils.get_tcb(self.pid)) + + def __str__(self): + args = [ + self.taskname, + ] + if CONFIG_SMP: + args.append(self.cpu) + args.extend([self.pid, self.notetype, self.args]) + return ( + "[%s] " + ("[CPU%d] " if CONFIG_SMP else "") + "[%d] %-16s %#x" + ) % tuple(args) + + +class NoteSnap(gdb.Command): + """Dump notesnap""" + + def __init__(self): + if not CONFIG_DRIVERS_NOTESNAP_NBUFFERS: + return + super().__init__("notesnap", gdb.COMMAND_USER) + + def parse_notesnap(self): + """Parse note snapshot data""" + + notesnap = utils.parse_and_eval("g_notesnap") + notesnap_type = utils.parse_and_eval("g_notesnap_type") + output = [] + + for note in utils.ArrayIterator(notesnap.buffer): + if not note: + continue + + chunk = { + "notetype": notesnap_type[note["type"]].string(), + "pid": note.pid, + "args": note.args, + "cpu": note.cpu if CONFIG_SMP else 0, + } + + output.append(NoteSnapChunk(**chunk)) + return output + + def diagnose(self, *args, **kwargs): + return { + "title": "Notesnap Report", + "summary": "notesnap dump", + "command": "notesnap", + "result": "pass", + "message": self.parse_notesnap(), + } + + def invoke(self, args, from_tty): + try: + print(*(self.parse_notesnap()), sep="\n") + except Exception as e: + print(f"Error happened during notesnap: {e}") diff --git a/tools/pynuttx/nxgdb/pm.py b/tools/pynuttx/nxgdb/pm.py new file mode 100644 index 00000000000..37ee4220ec3 --- /dev/null +++ b/tools/pynuttx/nxgdb/pm.py @@ -0,0 +1,103 @@ +############################################################################ +# tools/pynuttx/nxgdb/pm.py +# +# SPDX-License-Identifier: Apache-2.0 +# +# Licensed to the Apache Software Foundation (ASF) under one or more +# contributor license agreements. See the NOTICE file distributed with +# this work for additional information regarding copyright ownership. The +# ASF licenses this file to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance with the +# License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# +############################################################################ + +import gdb + +from . import utils + +PM_COUNT = utils.get_symbol_value("PM_COUNT") + + +class PMStateInfo: + def __init__(self, wake_time, sleep_time): + self.wake_time = wake_time + self.sleep_time = sleep_time + self.total_time = wake_time + sleep_time + + +def has_inferior(): + inferior = gdb.selected_inferior() + return inferior is not None and inferior.is_valid() + + +def get_pm_state_info_list(domain): + state_info_list = [] + sum_time = 0 + + for state in range(PM_COUNT): + wake_time = int(domain["wake"][state]["tv_sec"]) + sleep_time = int(domain["sleep"][state]["tv_sec"]) + + sum_time += wake_time + sleep_time + state_info_list.append(PMStateInfo(wake_time, sleep_time)) + + sum_time = sum_time if sum_time > 0 else 1 + return state_info_list, sum_time + + +class Pmconfig(gdb.Command): + """Display power management configuration information + + Usage: pmconfig + """ + + state_formatter = "{:<12} {:<12} {:<12} {:<12}" + state_header = ("WAKE", "SLEEP", "TOTAL") + + def __init__(self): + super().__init__("pmconfig", gdb.COMMAND_USER) + + def get_time_str(self, time_val, sum_time): + percentage = (time_val / sum_time) * 100 if sum_time > 0 else 0 + return f"{int(time_val)}s {int(percentage):02}%" + + def print_state_info(self, domain_name, domain): + state_path = f"/proc/pm/state{domain_name[-1]}" + gdb.write(f"{state_path}:\n") + gdb.write(self.state_formatter.format(domain_name, *self.state_header) + "\n") + + state_info_list, sum_time = get_pm_state_info_list(domain) + pm_state = gdb.parse_and_eval("g_pm_state") + + for state in range(PM_COUNT): + state_info = state_info_list[state] + wake_str = self.get_time_str(state_info.wake_time, sum_time) + sleep_str = self.get_time_str(state_info.sleep_time, sum_time) + total_str = self.get_time_str(state_info.total_time, sum_time) + + state_name = pm_state[state].string() + gdb.write( + self.state_formatter.format(state_name, wake_str, sleep_str, total_str) + + "\n" + ) + + def invoke(self, arg: str, from_tty: bool) -> None: + if not has_inferior(): + return + + pmdomains = gdb.parse_and_eval("g_pmdomains") + ndomains = utils.nitems(pmdomains) + + domains = [f"DOMAIN{i}" for i in range(ndomains)] + for i, domain_name in enumerate(domains): + domain = pmdomains[i] + self.print_state_info(domain_name, domain) diff --git a/tools/pynuttx/nxgdb/utils.py b/tools/pynuttx/nxgdb/utils.py index e086bb8267b..435abfd1526 100644 --- a/tools/pynuttx/nxgdb/utils.py +++ b/tools/pynuttx/nxgdb/utils.py @@ -810,9 +810,9 @@ def get_tcbs() -> List[Tcb]: def get_tcb(pid) -> Tcb: """get tcb from pid""" - g_pidhash = parse_and_eval("g_pidhash") - g_npidhash = parse_and_eval("g_npidhash") - tcb = g_pidhash[pid & (g_npidhash - 1)] + pidhash = parse_and_eval("g_pidhash") + npidhash = parse_and_eval("g_npidhash") + tcb = pidhash[pid & (npidhash - 1)] if not tcb or pid != tcb["pid"]: return None diff --git a/tools/pynuttx/nxstub/target.py b/tools/pynuttx/nxstub/target.py index c1723630793..a2557929cbb 100644 --- a/tools/pynuttx/nxstub/target.py +++ b/tools/pynuttx/nxstub/target.py @@ -128,18 +128,18 @@ class Target: # Fallback to pure number. Don't bother to parse value of NUM_TASK_STATES, 256 is enough. states = [str(i) for i in range(256)] - g_npidhash, sym = self._read_int("g_npidhash") - self.logger.debug(f"g_npidhash: {g_npidhash}@{sym.value:#x}") - if not g_npidhash: - self.logger.error(f"No threads info found: {g_npidhash}") + npidhash, sym = self._read_int("g_npidhash") + self.logger.debug(f"g_npidhash: {npidhash}@{sym.value:#x}") + if not npidhash: + self.logger.error(f"No threads info found: {npidhash}") return self.threads ncpus = utils.get_ncpus(self.elf) regsize = utils.get_regsize(self.elf) data, sym = self._read_symbol("g_running_tasks") # an array of pointers - g_running_tasks = utils.parse_array(data, pointer, ncpus) - self.logger.debug(f"g_running_tasks: {g_running_tasks}@{sym.value:#x}") + running_tasks = utils.parse_array(data, pointer, ncpus) + self.logger.debug(f"g_running_tasks: {running_tasks}@{sym.value:#x}") def parse_tcb(address: int) -> ThreadInfo: registers = Registers( @@ -160,12 +160,12 @@ class Target: state = utils.uint8_t(data[tcbinfo.state_off : tcbinfo.state_off + 1]) state = states[state] if state < len(states) else "Unknown" - if address in g_running_tasks: + if address in running_tasks: # Running task registers is not in memory, best chance is the registers # stored in g_last_regs when assert happened. - g_last_regs = self.elf.get_symbol("g_last_regs").value - cpu = g_running_tasks.index(address) - xcpregs = cpu * regsize + g_last_regs + last_regs = self.elf.get_symbol("g_last_regs").value + cpu = running_tasks.index(address) + xcpregs = cpu * regsize + last_regs else: off = tcbinfo.regs_off xcpregs = data[off : off + pointer.sizeof()] @@ -180,12 +180,12 @@ class Target: return ThreadInfo(name, pid, state, registers) data, sym = self._read_symbol("g_pidhash") - g_pidhash = pointer.parse(data) - data = self.memory_read(g_pidhash, pointer.sizeof() * g_npidhash) - g_pidhash = utils.parse_array(data, pointer, g_npidhash) - self.logger.debug(f"g_pidhash: {g_pidhash}@{sym.value:#x}") + pidhash = pointer.parse(data) + data = self.memory_read(pidhash, pointer.sizeof() * npidhash) + pidhash = utils.parse_array(data, pointer, npidhash) + self.logger.debug(f"g_pidhash: {pidhash}@{sym.value:#x}") - self.threads = [parse_tcb(tcb) for tcb in g_pidhash if tcb] + self.threads = [parse_tcb(tcb) for tcb in pidhash if tcb] self.logger.debug(f"Found {self.threads}") except Exception as e: self.logger.error(f"No threads info: {e}\n{traceback.format_exc()}") diff --git a/tools/pynuttx/nxstub/utils.py b/tools/pynuttx/nxstub/utils.py index 8c9f57cba3c..19704de1479 100644 --- a/tools/pynuttx/nxstub/utils.py +++ b/tools/pynuttx/nxstub/utils.py @@ -32,9 +32,9 @@ def get_ncpus(elf: LiefELF) -> int: # FAR struct tcb_s *g_running_tasks[CONFIG_SMP_NCPUS]; # # g_running_tasks is an pointer array in length of ncpu - g_running_tasks = elf.get_symbol("g_running_tasks") + running_tasks = elf.get_symbol("g_running_tasks") - return g_running_tasks.size // elf.get_pointer_size() + return running_tasks.size // elf.get_pointer_size() def get_regsize(elf: LiefELF) -> int: @@ -63,9 +63,9 @@ def get_tcb_size(elf: LiefELF) -> int: # static struct tcb_s g_idletcb[CONFIG_SMP_NCPUS]; # Idle TCB happen to be an array of tcb_s - g_idletcb = elf.get_symbol("g_idletcb") + idletcb = elf.get_symbol("g_idletcb") ncpus = get_ncpus(elf) - return g_idletcb.size // ncpus + return idletcb.size // ncpus def parse_array(data, type_, narray): -- Gitee From 1eaca21fc5dbea7fe28ba1e0d31eb61bb45581c5 Mon Sep 17 00:00:00 2001 From: yangao1 Date: Mon, 10 Mar 2025 15:34:39 +0800 Subject: [PATCH 098/235] nxreg/register.py:modify offset for regs VELAPLATFO-57109 Change-Id: I4ba47e0fb0a2cc71a4c38f3ce07fd76c7ecf51d2 Signed-off-by: yangao1 --- tools/pynuttx/nxreg/register.py | 313 ++++++++++++++++---------------- 1 file changed, 157 insertions(+), 156 deletions(-) diff --git a/tools/pynuttx/nxreg/register.py b/tools/pynuttx/nxreg/register.py index 2d42927237e..946b0f8b291 100644 --- a/tools/pynuttx/nxreg/register.py +++ b/tools/pynuttx/nxreg/register.py @@ -26,6 +26,7 @@ from construct import Array, Int8ul, Int16ul, PaddedString, Struct from nxelf.elf import LiefELF UINT16_MAX = 0xFFFF +REGINFO_OFFSET_AUTO = 0 g_reg_table = { "arm": { @@ -41,45 +42,45 @@ g_reg_table = { ], "feature": "org.gnu.gdb.arm.m-profile", "registers": [ - ("r0", 0, 0), - ("r1", 1, 0), - ("r2", 2, 0), - ("r3", 3, 0), - ("r4", 4, 0), - ("r5", 5, 0), - ("r6", 6, 0), - ("r7", 7, 0), - ("r8", 8, 0), - ("r9", 9, 0), - ("r10", 10, 0), - ("r11", 11, 0), - ("r12", 12, 0), - ("sp", 13, 0), - ("lr", 14, 0), - ("pc", 15, 0), - ("xpsr", 25, 0), + ("r0", 0, REGINFO_OFFSET_AUTO), + ("r1", 1, REGINFO_OFFSET_AUTO), + ("r2", 2, REGINFO_OFFSET_AUTO), + ("r3", 3, REGINFO_OFFSET_AUTO), + ("r4", 4, REGINFO_OFFSET_AUTO), + ("r5", 5, REGINFO_OFFSET_AUTO), + ("r6", 6, REGINFO_OFFSET_AUTO), + ("r7", 7, REGINFO_OFFSET_AUTO), + ("r8", 8, REGINFO_OFFSET_AUTO), + ("r9", 9, REGINFO_OFFSET_AUTO), + ("r10", 10, REGINFO_OFFSET_AUTO), + ("r11", 11, REGINFO_OFFSET_AUTO), + ("r12", 12, REGINFO_OFFSET_AUTO), + ("sp", 13, REGINFO_OFFSET_AUTO), + ("lr", 14, REGINFO_OFFSET_AUTO), + ("pc", 15, REGINFO_OFFSET_AUTO), + ("xpsr", 25, REGINFO_OFFSET_AUTO), ], }, "arm-a": { "architecture": ["armv6", "armv7", "armv8-a", "armv8-r", "armv9-a"], "feature": "org.gnu.gdb.arm", "registers": [ - ("r0", 0, 0), - ("r1", 1, 0), - ("r2", 2, 0), - ("r3", 3, 0), - ("r4", 4, 0), - ("r5", 5, 0), - ("r6", 6, 0), - ("r7", 7, 0), - ("r8", 8, 0), - ("r9", 9, 0), - ("r10", 10, 0), - ("r11", 11, 0), - ("r12", 12, 0), - ("sp", 13, 0), - ("lr", 14, 0), - ("pc", 15, 0), + ("r0", 0, REGINFO_OFFSET_AUTO), + ("r1", 1, REGINFO_OFFSET_AUTO), + ("r2", 2, REGINFO_OFFSET_AUTO), + ("r3", 3, REGINFO_OFFSET_AUTO), + ("r4", 4, REGINFO_OFFSET_AUTO), + ("r5", 5, REGINFO_OFFSET_AUTO), + ("r6", 6, REGINFO_OFFSET_AUTO), + ("r7", 7, REGINFO_OFFSET_AUTO), + ("r8", 8, REGINFO_OFFSET_AUTO), + ("r9", 9, REGINFO_OFFSET_AUTO), + ("r10", 10, REGINFO_OFFSET_AUTO), + ("r11", 11, REGINFO_OFFSET_AUTO), + ("r12", 12, REGINFO_OFFSET_AUTO), + ("sp", 13, REGINFO_OFFSET_AUTO), + ("lr", 14, REGINFO_OFFSET_AUTO), + ("pc", 15, REGINFO_OFFSET_AUTO), ("cpsr", 25, 164), ], }, @@ -87,107 +88,107 @@ g_reg_table = { "architecture": ["aarch64", "aarch64:ilp32", "aarch64:armv8-r"], "feature": "org.gnu.gdb.aarch64", "registers": [ - ("x0", 0, 0), - ("x1", 1, 0), - ("x2", 2, 0), - ("x3", 3, 0), - ("x4", 4, 0), - ("x5", 5, 0), - ("x6", 6, 0), - ("x7", 7, 0), - ("x8", 8, 0), - ("x9", 9, 0), - ("x10", 10, 0), - ("x11", 11, 0), - ("x12", 12, 0), - ("x13", 13, 0), - ("x14", 14, 0), - ("x15", 15, 0), - ("x16", 16, 0), - ("x17", 17, 0), - ("x18", 18, 0), - ("x19", 19, 0), - ("x20", 20, 0), - ("x21", 21, 0), - ("x22", 22, 0), - ("x23", 23, 0), - ("x24", 24, 0), - ("x25", 25, 0), - ("x26", 26, 0), - ("x27", 27, 0), - ("x28", 28, 0), - ("x29", 29, 0), - ("x30", 30, 0), - ("sp_elx", 31, 0), # SP - ("elr", 32, 0), # PC + ("x0", 0, REGINFO_OFFSET_AUTO), + ("x1", 1, REGINFO_OFFSET_AUTO), + ("x2", 2, REGINFO_OFFSET_AUTO), + ("x3", 3, REGINFO_OFFSET_AUTO), + ("x4", 4, REGINFO_OFFSET_AUTO), + ("x5", 5, REGINFO_OFFSET_AUTO), + ("x6", 6, REGINFO_OFFSET_AUTO), + ("x7", 7, REGINFO_OFFSET_AUTO), + ("x8", 8, REGINFO_OFFSET_AUTO), + ("x9", 9, REGINFO_OFFSET_AUTO), + ("x10", 10, REGINFO_OFFSET_AUTO), + ("x11", 11, REGINFO_OFFSET_AUTO), + ("x12", 12, REGINFO_OFFSET_AUTO), + ("x13", 13, REGINFO_OFFSET_AUTO), + ("x14", 14, REGINFO_OFFSET_AUTO), + ("x15", 15, REGINFO_OFFSET_AUTO), + ("x16", 16, REGINFO_OFFSET_AUTO), + ("x17", 17, REGINFO_OFFSET_AUTO), + ("x18", 18, REGINFO_OFFSET_AUTO), + ("x19", 19, REGINFO_OFFSET_AUTO), + ("x20", 20, REGINFO_OFFSET_AUTO), + ("x21", 21, REGINFO_OFFSET_AUTO), + ("x22", 22, REGINFO_OFFSET_AUTO), + ("x23", 23, REGINFO_OFFSET_AUTO), + ("x24", 24, REGINFO_OFFSET_AUTO), + ("x25", 25, REGINFO_OFFSET_AUTO), + ("x26", 26, REGINFO_OFFSET_AUTO), + ("x27", 27, REGINFO_OFFSET_AUTO), + ("x28", 28, REGINFO_OFFSET_AUTO), + ("x29", 29, REGINFO_OFFSET_AUTO), + ("x30", 30, REGINFO_OFFSET_AUTO), + ("sp_elx", 31, REGINFO_OFFSET_AUTO), # SP + ("elr", 32, REGINFO_OFFSET_AUTO), # PC ], }, "riscv": { "architecture": ["riscv", "riscv:rv32", "riscv:rv64"], "feature": "org.gnu.gdb.riscv:rv32", "registers": [ - ("zero", 0, 0), - ("ra", 1, 0), - ("sp", 2, 0), - ("gp", 3, 0), - ("tp", 4, 0), - ("t0", 5, 0), - ("t1", 6, 0), - ("t2", 7, 0), - ("fp", 8, 0), - ("s1", 9, 0), - ("a0", 10, 0), - ("a1", 11, 0), - ("a2", 12, 0), - ("a3", 13, 0), - ("a4", 14, 0), - ("a5", 15, 0), - ("a6", 16, 0), - ("a7", 17, 0), - ("s2", 18, 0), - ("s3", 19, 0), - ("s4", 20, 0), - ("s5", 21, 0), - ("s6", 22, 0), - ("s7", 23, 0), - ("s8", 24, 0), - ("s9", 25, 0), - ("s10", 26, 0), - ("s11", 27, 0), - ("t3", 28, 0), - ("t4", 29, 0), - ("t5", 30, 0), - ("t6", 31, 0), - ("epc", 33, 0), # PC + ("zero", 0, REGINFO_OFFSET_AUTO), + ("ra", 1, REGINFO_OFFSET_AUTO), + ("sp", 2, REGINFO_OFFSET_AUTO), + ("gp", 3, REGINFO_OFFSET_AUTO), + ("tp", 4, REGINFO_OFFSET_AUTO), + ("t0", 5, REGINFO_OFFSET_AUTO), + ("t1", 6, REGINFO_OFFSET_AUTO), + ("t2", 7, REGINFO_OFFSET_AUTO), + ("fp", 8, REGINFO_OFFSET_AUTO), + ("s1", 9, REGINFO_OFFSET_AUTO), + ("a0", 10, REGINFO_OFFSET_AUTO), + ("a1", 11, REGINFO_OFFSET_AUTO), + ("a2", 12, REGINFO_OFFSET_AUTO), + ("a3", 13, REGINFO_OFFSET_AUTO), + ("a4", 14, REGINFO_OFFSET_AUTO), + ("a5", 15, REGINFO_OFFSET_AUTO), + ("a6", 16, REGINFO_OFFSET_AUTO), + ("a7", 17, REGINFO_OFFSET_AUTO), + ("s2", 18, REGINFO_OFFSET_AUTO), + ("s3", 19, REGINFO_OFFSET_AUTO), + ("s4", 20, REGINFO_OFFSET_AUTO), + ("s5", 21, REGINFO_OFFSET_AUTO), + ("s6", 22, REGINFO_OFFSET_AUTO), + ("s7", 23, REGINFO_OFFSET_AUTO), + ("s8", 24, REGINFO_OFFSET_AUTO), + ("s9", 25, REGINFO_OFFSET_AUTO), + ("s10", 26, REGINFO_OFFSET_AUTO), + ("s11", 27, REGINFO_OFFSET_AUTO), + ("t3", 28, REGINFO_OFFSET_AUTO), + ("t4", 29, REGINFO_OFFSET_AUTO), + ("t5", 30, REGINFO_OFFSET_AUTO), + ("t6", 31, REGINFO_OFFSET_AUTO), + ("epc", 33, REGINFO_OFFSET_AUTO), # PC ], }, "x86-64": { "architecture": ["i386", "i386:x86-64", "i386:x86-64:intel", "i386:intel"], "feature": "org.gnu.gdb.i386:x86-64", "registers": [ - ("rax", 0, 0), - ("rbx", 1, 0), - ("rcx", 2, 0), - ("rdx", 3, 0), - ("rsi", 4, 0), - ("rdi", 5, 0), - ("rbp", 6, 0), - ("fsp", 7, 0), - ("r8", 8, 0), - ("r9", 9, 0), - ("r10", 10, 0), - ("r11", 11, 0), - ("r12", 12, 0), - ("r13", 13, 0), - ("r14", 14, 0), - ("r15", 15, 0), - ("rip", 16, 0), - ("rflags", 17, 0), - ("cs", 18, 0), - ("ss", 19, 0), - ("ds", 20, 0), - ("es", 21, 0), - ("fs", 22, 0), + ("rax", 0, REGINFO_OFFSET_AUTO), + ("rbx", 1, REGINFO_OFFSET_AUTO), + ("rcx", 2, REGINFO_OFFSET_AUTO), + ("rdx", 3, REGINFO_OFFSET_AUTO), + ("rsi", 4, REGINFO_OFFSET_AUTO), + ("rdi", 5, REGINFO_OFFSET_AUTO), + ("rbp", 6, REGINFO_OFFSET_AUTO), + ("fsp", 7, REGINFO_OFFSET_AUTO), + ("r8", 8, REGINFO_OFFSET_AUTO), + ("r9", 9, REGINFO_OFFSET_AUTO), + ("r10", 10, REGINFO_OFFSET_AUTO), + ("r11", 11, REGINFO_OFFSET_AUTO), + ("r12", 12, REGINFO_OFFSET_AUTO), + ("r13", 13, REGINFO_OFFSET_AUTO), + ("r14", 14, REGINFO_OFFSET_AUTO), + ("r15", 15, REGINFO_OFFSET_AUTO), + ("rip", 16, REGINFO_OFFSET_AUTO), + ("rflags", 17, REGINFO_OFFSET_AUTO), + ("cs", 18, REGINFO_OFFSET_AUTO), + ("ss", 19, REGINFO_OFFSET_AUTO), + ("ds", 20, REGINFO_OFFSET_AUTO), + ("es", 21, REGINFO_OFFSET_AUTO), + ("fs", 22, REGINFO_OFFSET_AUTO), ], }, "esp32s3": { @@ -196,23 +197,23 @@ g_reg_table = { "registers": [ ("pc", 0, 0), ("ps", 73, 292, 0x40000), # g_reg_offs placed it in the second position - ("a0", 1, 0), - ("a1", 2, 0), - ("a2", 3, 0), - ("a3", 4, 0), - ("a4", 5, 0), - ("a5", 6, 0), - ("a6", 7, 0), - ("a7", 8, 0), - ("a8", 9, 0), - ("a9", 10, 0), - ("a10", 11, 0), - ("a11", 12, 0), - ("a12", 13, 0), - ("a13", 14, 0), - ("a14", 15, 0), - ("a15", 16, 0), - ("windowbase", 69, 276, 0), + ("a0", 1, REGINFO_OFFSET_AUTO), + ("a1", 2, REGINFO_OFFSET_AUTO), + ("a2", 3, REGINFO_OFFSET_AUTO), + ("a3", 4, REGINFO_OFFSET_AUTO), + ("a4", 5, REGINFO_OFFSET_AUTO), + ("a5", 6, REGINFO_OFFSET_AUTO), + ("a6", 7, REGINFO_OFFSET_AUTO), + ("a7", 8, REGINFO_OFFSET_AUTO), + ("a8", 9, REGINFO_OFFSET_AUTO), + ("a9", 10, REGINFO_OFFSET_AUTO), + ("a10", 11, REGINFO_OFFSET_AUTO), + ("a11", 12, REGINFO_OFFSET_AUTO), + ("a12", 13, REGINFO_OFFSET_AUTO), + ("a13", 14, REGINFO_OFFSET_AUTO), + ("a14", 15, REGINFO_OFFSET_AUTO), + ("a15", 16, REGINFO_OFFSET_AUTO), + ("windowbase", 69, 276, REGINFO_OFFSET_AUTO), ("windowstart", 70, 280, 1), ], }, @@ -220,25 +221,25 @@ g_reg_table = { "architecture": ["xtensa"], # Use xt-gdb "feature": "", "registers": [ - ("pc", 32, 0), + ("pc", 32, REGINFO_OFFSET_AUTO), ("ps", 742, 472, 0x40000), ("a0", 256, 4), - ("a1", 257, 0), - ("a2", 258, 0), - ("a3", 259, 0), - ("a4", 260, 0), - ("a5", 261, 0), - ("a6", 262, 0), - ("a7", 263, 0), - ("a8", 264, 0), - ("a9", 265, 0), - ("a10", 266, 0), - ("a11", 267, 0), - ("a12", 268, 0), - ("a13", 269, 0), - ("a14", 270, 0), - ("a15", 271, 0), - ("windowbase", 584, 308, 0), + ("a1", 257, REGINFO_OFFSET_AUTO), + ("a2", 258, REGINFO_OFFSET_AUTO), + ("a3", 259, REGINFO_OFFSET_AUTO), + ("a4", 260, REGINFO_OFFSET_AUTO), + ("a5", 261, REGINFO_OFFSET_AUTO), + ("a6", 262, REGINFO_OFFSET_AUTO), + ("a7", 263, REGINFO_OFFSET_AUTO), + ("a8", 264, REGINFO_OFFSET_AUTO), + ("a9", 265, REGINFO_OFFSET_AUTO), + ("a10", 266, REGINFO_OFFSET_AUTO), + ("a11", 267, REGINFO_OFFSET_AUTO), + ("a12", 268, REGINFO_OFFSET_AUTO), + ("a13", 269, REGINFO_OFFSET_AUTO), + ("a14", 270, REGINFO_OFFSET_AUTO), + ("a15", 271, REGINFO_OFFSET_AUTO), + ("windowbase", 584, 308, REGINFO_OFFSET_AUTO), ("windowstart", 585, 312, 1), ], }, -- Gitee From 03a355fea3d2464823e6dcc9fa85acc31d9ea363 Mon Sep 17 00:00:00 2001 From: yangao1 Date: Fri, 7 Mar 2025 16:25:21 +0800 Subject: [PATCH 099/235] pynuttx/nxreg/register.py:modify riscv and arm64 register VELAPLATFO-57109 Change-Id: I3cf066350298a21f23a365bc08eed212f439a930 Signed-off-by: yangao1 --- tools/pynuttx/nxreg/register.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tools/pynuttx/nxreg/register.py b/tools/pynuttx/nxreg/register.py index 946b0f8b291..47f9edd4931 100644 --- a/tools/pynuttx/nxreg/register.py +++ b/tools/pynuttx/nxreg/register.py @@ -119,8 +119,8 @@ g_reg_table = { ("x28", 28, REGINFO_OFFSET_AUTO), ("x29", 29, REGINFO_OFFSET_AUTO), ("x30", 30, REGINFO_OFFSET_AUTO), - ("sp_elx", 31, REGINFO_OFFSET_AUTO), # SP - ("elr", 32, REGINFO_OFFSET_AUTO), # PC + ("sp", 31, REGINFO_OFFSET_AUTO), # SP + ("pc", 32, REGINFO_OFFSET_AUTO), # PC ], }, "riscv": { @@ -159,7 +159,7 @@ g_reg_table = { ("t4", 29, REGINFO_OFFSET_AUTO), ("t5", 30, REGINFO_OFFSET_AUTO), ("t6", 31, REGINFO_OFFSET_AUTO), - ("epc", 33, REGINFO_OFFSET_AUTO), # PC + ("pc", 33, REGINFO_OFFSET_AUTO), # PC ], }, "x86-64": { -- Gitee From faf900c5c7e3945c681345bc57b83b484a8f9095 Mon Sep 17 00:00:00 2001 From: yangao1 Date: Fri, 7 Mar 2025 16:32:25 +0800 Subject: [PATCH 100/235] nxreg/register.py:add tricore regs and modify function to load regs VELAPLATFO-57109 Change-Id: I89f1b2b558b7480313fb58e832004e1a4c5c7ee4 Signed-off-by: yangao1 --- tools/pynuttx/nxreg/register.py | 87 ++++++++++++++++++++++++++++++++- 1 file changed, 85 insertions(+), 2 deletions(-) diff --git a/tools/pynuttx/nxreg/register.py b/tools/pynuttx/nxreg/register.py index 47f9edd4931..a2ae4a1f47b 100644 --- a/tools/pynuttx/nxreg/register.py +++ b/tools/pynuttx/nxreg/register.py @@ -243,6 +243,43 @@ g_reg_table = { ("windowstart", 585, 312, 1), ], }, + "tricore": { + "architecture": "tricore", # Use tricore-gdb + "feature": "", + "registers": [ + ("pcx", 34, 136), + ("pc", 36, 144), + ("d0", 0, 0), + ("d1", 1, 4), + ("d2", 2, 8), + ("d3", 3, 12), + ("d4", 4, 16), + ("d5", 5, 20), + ("d6", 6, 24), + ("d7", 7, 28), + ("a2", 18, 72), + ("a3", 19, 76), + ("a4", 20, 80), + ("a5", 21, 84), + ("a6", 22, 88), + ("a7", 23, 92), + ("psw", 35, 140), + ("sp", 26, 104), + ("a11", 27, 108), + ("d8", 8, 32), + ("d9", 9, 36), + ("d10", 10, 40), + ("d11", 11, 44), + ("a12", 28, 112), + ("a13", 29, 116), + ("a14", 30, 120), + ("a15", 31, 124), + ("d12", 12, 48), + ("d13", 13, 52), + ("d14", 14, 56), + ("d15", 15, 60), + ], + }, } @@ -328,7 +365,7 @@ class Register: class GeneralRegisters: - def __init__(self, elf, arch=None, readmem=None): + def __init__(self, elf: LiefELF, arch=None, readmem=None): """ Registers class to store register information @@ -452,5 +489,51 @@ class GeneralRegisters: return self._registers[key] +class TricoreRegisters(GeneralRegisters): + def __init__(self, elf, arch=None, readmem=None): + super().__init__(elf, arch, readmem) + + # tricore read csa + def load(self, addr: int): + lower_count = 16 + upper_count = 16 + lpcx = None + xcpregs = self.readmem(addr, lower_count * 4) # read lower csa + xcp_table = [reg[0] for reg in g_reg_table["tricore"]["registers"]] + + if not xcpregs: + raise ValueError("No valid source to load register values.\n") + + for name in xcp_table[:lower_count]: + reg = self.get(name=name) + reg.value = xcpregs[reg.tcb_reg_off : reg.tcb_reg_off + reg.size] + if name == "pcx": + lpcx = reg.value + + if not lpcx: + raise ValueError("Invalid lpcx register loaded.\n") + + PCXI_UL = 1 << 20 # determine wheteher it is the upper csa flag + is_upper = (lpcx & PCXI_UL) != 0 + + def csa2addr(csa): + # #define tricore_csa2addr(csa) ((uintptr_t *)((((csa) & 0x000F0000) << 12) \ + # | (((csa) & 0x0000FFFF) << 6))) + return (csa & 0x000F0000) << 12 | (csa & 0x0000FFFF) << 6 + + if is_upper: + xcpregs = self.readmem(csa2addr(lpcx), upper_count * 4) + for name in xcp_table[lower_count:]: + reg = self.get(name=name) + if reg.tcb_reg_off + reg.size > len(xcpregs): + raise ValueError("No valid source to load register values.\n") + reg.value = xcpregs[reg.tcb_reg_off : reg.tcb_reg_off + reg.size] + + return self + + def Registers(elf, arch=None, readmem=None) -> GeneralRegisters: - return GeneralRegisters(elf, arch, readmem) + if arch == "tricore": + return TricoreRegisters(elf, arch, readmem) + else: + return GeneralRegisters(elf, arch, readmem) -- Gitee From b1c5c4badd383bf2179f18bff9a2ffa0c6d898b9 Mon Sep 17 00:00:00 2001 From: xuxingliang Date: Fri, 28 Mar 2025 10:24:43 +0800 Subject: [PATCH 101/235] nxgdb/dmesg: fix exception when read 0 length of memory VELAPLATFO-57259 Change-Id: Ibe36f20fe1e04c2142785821c4742e7def75fd45 Signed-off-by: xuxingliang (cherry picked from commit 5144f675e0332a820b7d54cc5aeb5ca8fa5f4e83) --- tools/pynuttx/nxgdb/dmesg.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/tools/pynuttx/nxgdb/dmesg.py b/tools/pynuttx/nxgdb/dmesg.py index c4c8b028091..84b7d66200f 100644 --- a/tools/pynuttx/nxgdb/dmesg.py +++ b/tools/pynuttx/nxgdb/dmesg.py @@ -45,9 +45,9 @@ class Dmesg(gdb.Command): rl_buffer = int(rl_header["rl_buffer"].address) # rl_buffer is a char array inf = gdb.selected_inferior() - buf = bytes(inf.read_memory(offset + rl_buffer, tail)) + buf = bytes(inf.read_memory(offset + rl_buffer, tail) if tail else b"") buf = buf.lstrip(b"\0") # Remove leading NULLs - buf += bytes(inf.read_memory(rl_buffer, offset)) + buf += bytes(inf.read_memory(rl_buffer, offset) if offset else b"") buf = buf.replace( b"\0", "␀".encode("utf-8") ) # NULL is valid utf-8 but not printable @@ -58,7 +58,8 @@ class Dmesg(gdb.Command): if not (priv := utils.gdb_eval_or_none("g_syslog_rpmsg")): return "RPMsg syslog not avaliable" - buffer = bytes(gdb.selected_inferior().read_memory(priv.buffer, priv.size)) + inf = gdb.selected_inferior() + buffer = bytes(inf.read_memory(priv.buffer, priv.size) if priv.size else b"") buf = buffer.replace(b"\0", "␀".encode("utf-8")) return buf.decode("utf-8", errors="replace") -- Gitee From d2731a1829a07c5f18c65ce95fd63fd84aa3e568 Mon Sep 17 00:00:00 2001 From: xuxingliang Date: Mon, 20 Jan 2025 22:16:12 +0800 Subject: [PATCH 102/235] nxgdb/libuv: fix path in comment VELAPLATFO-45245 Change-Id: I1e2c7269b8bab7b7c866fa6f19c3cf9ddcd07493 Signed-off-by: xuxingliang --- tools/pynuttx/nxgdb/libuv.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/pynuttx/nxgdb/libuv.py b/tools/pynuttx/nxgdb/libuv.py index 7be299581cd..77633f7c37e 100644 --- a/tools/pynuttx/nxgdb/libuv.py +++ b/tools/pynuttx/nxgdb/libuv.py @@ -1,5 +1,5 @@ ############################################################################ -# apps/system/libuv/gdb/libuv.py +# tools/pynuttx/nxgdb/libuv.py # # Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with -- Gitee From 6fa2887f2846f28f9a19dde06fd06f1cd508d967 Mon Sep 17 00:00:00 2001 From: xuxingliang Date: Tue, 21 Jan 2025 10:29:35 +0800 Subject: [PATCH 103/235] nxgdb/fs: fix failed to format gdb.Value VELAPLATFO-52621 On trunk branch, need patch https://gerrit.pt.mioffice.cn/c/vela/nuttx/+/4891676 to get the macro value CONFIG_NFILE_DESCRIPTORS_PER_BLOCK reliably. Change-Id: Ibd17ee2f61e7eedb888cc27c449ab35055ecdc27 Signed-off-by: xuxingliang --- tools/pynuttx/nxgdb/fs.py | 1 + 1 file changed, 1 insertion(+) diff --git a/tools/pynuttx/nxgdb/fs.py b/tools/pynuttx/nxgdb/fs.py index a0382c1ac99..c0d77ac1109 100644 --- a/tools/pynuttx/nxgdb/fs.py +++ b/tools/pynuttx/nxgdb/fs.py @@ -47,6 +47,7 @@ if CONFIG_NFILE_DESCRIPTORS_PER_BLOCK is None: CONFIG_NFILE_DESCRIPTORS_PER_BLOCK = ( int(utils.gdb_eval_or_none("CONFIG_NFILE_DESCRIPTORS_PER_BLOCK")) or 8 ) + CONFIG_NFILE_DESCRIPTORS_PER_BLOCK = int(CONFIG_NFILE_DESCRIPTORS_PER_BLOCK) g_special_inodes = {} # Map of the special inodes including epoll, inotify, etc. -- Gitee From f587a24524d05732d07730faedf31998c586559d Mon Sep 17 00:00:00 2001 From: yangao1 Date: Tue, 21 Jan 2025 21:12:29 +0800 Subject: [PATCH 104/235] nxgdb/rpmsg.py:add dump rpmsg port message VELAPLATFO-52584 (gdb)rpmsgdump -t Change-Id: I6031f017571c047b679d2772dc381554c48b8cf5 Signed-off-by: yangao1 --- tools/pynuttx/nxgdb/rpmsg.py | 51 ++++++++++++++++++++++++++++++++++++ 1 file changed, 51 insertions(+) diff --git a/tools/pynuttx/nxgdb/rpmsg.py b/tools/pynuttx/nxgdb/rpmsg.py index 2e7ed5bd60a..e92e891ac06 100644 --- a/tools/pynuttx/nxgdb/rpmsg.py +++ b/tools/pynuttx/nxgdb/rpmsg.py @@ -124,6 +124,56 @@ class RPMsgDump(gdb.Command): gdb.write("\n") + def rpmsg_get_ept_from_addr(self, rdev, addr): + endpoints = rdev["endpoints"] + for endpoint in NxList(endpoints, "struct rpmsg_endpoint", "node"): + ept_addr = endpoint["addr"] + if ept_addr == addr: + return endpoint + return None + + def rpmsg_port_node_to_buf(self, queue, node): + node_offset = int(node) - int(queue["node"]) + buf_addr = queue["buf"] + (node_offset * queue["len"]) + return buf_addr + + def dump_rpmsg_port_buffer(self, rdev, queue, label): + buffer_list = [] + head = queue["ready"]["head"] + + for node in NxList(head): + hdr = self.rpmsg_port_node_to_buf(queue, node) + if not hdr or not hdr["buf"]: + continue + + rphdr = hdr["buf"].cast(utils.lookup_type("struct rpmsg_hdr").pointer()) + ept_addr = rphdr["dst"] if label == "RX" else rphdr["src"] + ept = self.rpmsg_get_ept_from_addr(rdev, ept_addr) + if ept: + ept_name = ept["name"].string().split("\0", 1)[0] + buffer_list.append(f"{label} buffer:{rphdr} held by {ept_name}\n") + + return buffer_list + + def dump_rpmsg_port(self, rdev): + real_addr = hex( + gdb.lookup_symbol("rpmsg_port_get_tx_payload_buffer")[0].value().address + ) + ops_addr = hex(int(utils.Value(rdev["ops"]["get_tx_payload_buffer"])) & ~1) + if real_addr != ops_addr: + return + port = rdev.cast(utils.lookup_type("struct rpmsg_port_s").pointer()) + + gdb.write(f"rxq nused:{port['rxq']['ready']['num']}\n") + gdb.write(f"rxq navail:{port['rxq']['free']['num']}\n") + gdb.write(f"txq nused:{port['txq']['ready']['num']}\n") + gdb.write(f"txq navail:{port['txq']['free']['num']}\n") + + rx_buffers = self.dump_rpmsg_port_buffer(rdev, port["rxq"], "RX") + tx_buffers = self.dump_rpmsg_port_buffer(rdev, port["txq"], "TX") + for buffer in rx_buffers + tx_buffers: + gdb.write(buffer + "\n") + def print_headers(self, headers, formatter): gdb.write(formatter.format(*headers) + "\n") gdb.write(formatter.format(*["-" * len(header) for header in headers]) + "\n") @@ -178,6 +228,7 @@ class RPMsgDump(gdb.Command): if not transport_only: self.dump_rdev(rpmsg["rdev"]) self.dump_rpmsg_virtio(rpmsg["rdev"]) + self.dump_rpmsg_port(rpmsg["rdev"]) def invoke(self, args, from_tty): if not (args := self.parse_args(args)): -- Gitee From bf5e5434e3d8c0825017987cf7fa9b27cbd56f51 Mon Sep 17 00:00:00 2001 From: gaoyulong Date: Tue, 7 Jan 2025 11:16:53 +0800 Subject: [PATCH 105/235] add memclassify tools in gdb VELAPLATFO-48980 example: (gdb) memclassify -p (gdb) memclassify -p -c size ----------------------------------total Mem Statistics---------------------------------- category | total mem size | memblk uniq cnt| memblk tot cnt | mem without overhead ---------------------------------------------------------------------------------------- quickjs | 26803200 | 5599 | 91662 | 22403424 graphic | 34854688 | 2492 | 15904 | 34091296 ... framework | 3232 | 10 | 10 | 2752 others | 76855168 | 13457 | 85678 | 72742624 total | 142489320 | 22002 | 200465 | 132867000 ---------------------------------------------------------------------------------------- ------------------------------total.graphic Mem Statistics------------------------------ category | total mem size | memblk uniq cnt| memblk tot cnt | mem without overhead ---------------------------------------------------------------------------------------- freetype_cache | 342704 | 68 | 886 | 300176 image_cache | 18304 | 6 | 104 | 13312 unknown | 34493680 | 2418 | 14914 | 33777808 total | 34854688 | 2492 | 15904 | 34091296 ---------------------------------------------------------------------------------------- Change-Id: I8198ccbe3ca174bb9e9c1c70e8fb0cc344572132 Signed-off-by: gaoyulong --- tools/pynuttx/nxgdb/memclassifier/default.py | 124 ++++++ tools/pynuttx/nxgdb/memclassifier/size.py | 28 ++ tools/pynuttx/nxgdb/memclassifier/utils.py | 41 ++ tools/pynuttx/nxgdb/memclassify.py | 374 +++++++++++++++++++ tools/pynuttx/nxgdb/utils.py | 16 +- 5 files changed, 582 insertions(+), 1 deletion(-) create mode 100644 tools/pynuttx/nxgdb/memclassifier/default.py create mode 100644 tools/pynuttx/nxgdb/memclassifier/size.py create mode 100644 tools/pynuttx/nxgdb/memclassifier/utils.py create mode 100644 tools/pynuttx/nxgdb/memclassify.py diff --git a/tools/pynuttx/nxgdb/memclassifier/default.py b/tools/pynuttx/nxgdb/memclassifier/default.py new file mode 100644 index 00000000000..068a5c2ac3c --- /dev/null +++ b/tools/pynuttx/nxgdb/memclassifier/default.py @@ -0,0 +1,124 @@ +############################################################################ +# tools/pynuttx/nxgdb/memclassifier/default.py +# +# Licensed to the Apache Software Foundation (ASF) under one or more +# contributor license agreements. See the NOTICE file distributed with +# this work for additional information regarding copyright ownership. The +# ASF licenses this file to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance with the +# License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# +############################################################################ + +from nxgdb.memclassifier.utils import ( + backtrace_function_name_contain, + backtrace_function_name_equal, + backtrace_function_name_startswith, +) + + +def is_quickjs(mb): + for funcname, filename in mb.backtrace(): + if funcname in ["js_def_malloc", "js_def_realloc"]: + return True + return False + + +def is_graphic(mb): + for funcname, filename in mb.backtrace(): + if funcname in [ + "ft_alloc", + "ft_realloc", + "FT_Stream_New", + "lv_mem_realloc", + "lv_mem_alloc", + "lv_malloc", + "lv_realloc", + "lv_malloc_zeroed", + "gui_context_init(bool)", + "gui_create_widget(void*, char const*)", + "ferry::WidgetDiv::setStyle(int, char const*)", + "ferry::WidgetIMP::onInit()", + "gui_get_taskinfo()", + "ferry::DomElement::refreshingWidgetStyle()", + "gui_create_context(bool)", + "ferry::DomEntity::updateWidgetChildren(ferry::DomEntity**)", + "ferry::DomElement::setAttr(ferry::ItemKeyValue const*)", + ]: + return True + + return False + + +def is_freetype_cache(mb): + for funcname, filename in mb.backtrace(): + if funcname in [ + "freetype_image_create_cb", + ]: + return True + return False + + +def is_image_cache(mb): + for funcname, filename in mb.backtrace(): + if funcname in [ + "freetype_image_create_cb", + ]: + return True + return False + + +def is_style(mb): + for funcname, filename in mb.backtrace(): + if any(funcname.startswith(func) for func in ["ferry::style::"]): + return True + return False + + +categories = { + "quickjs": is_quickjs, + "graphic": { + "judger": is_graphic, + "subcategories": { + "freetype_cache": {"judger": is_freetype_cache}, + "image_cache": {"judger": is_image_cache}, + }, + }, + "style": is_style, + "libuv": backtrace_function_name_equal(["uv__realloc", "uv_pipe"]), + "dom": backtrace_function_name_startswith(["js_dom_create", "ferry::PbDom"]), + "curl": backtrace_function_name_startswith(["Curl_"]), + "native_proxy": backtrace_function_name_startswith( + [ + "AIOTJS::js_nativeproxy_get", + "AIOTJS::ComponentCallHook::pauseTracking", + ] + ), + "rapidjson": backtrace_function_name_startswith( + ["rapidjson::ParseResult", "rapidjson::GenericReader"] + ), + "feature_require": backtrace_function_name_contain( + ["ferry::__app_require", "_onRequired"] + ), + "bundle": backtrace_function_name_startswith(["ferry::ZipFile::ZipFile"]), + "binder": backtrace_function_name_equal( + ["binder_mmap", "android::RefBase::RefBase()"] + ), + "framework": backtrace_function_name_startswith( + [ + "ferry::Application::initManifestConfig", + "ferry::PageLoader::createPage(ferry::PageInfo const&)", + "os::app::ApplicationThread::ApplicationThread(os::app::Application*)", + "ferry::AppLoader::initAppEnv(ferry::Application*", + ] + ), + "other": lambda mb: True, +} diff --git a/tools/pynuttx/nxgdb/memclassifier/size.py b/tools/pynuttx/nxgdb/memclassifier/size.py new file mode 100644 index 00000000000..e510b2c4d49 --- /dev/null +++ b/tools/pynuttx/nxgdb/memclassifier/size.py @@ -0,0 +1,28 @@ +############################################################################ +# tools/pynuttx/nxgdb/memclassifier/size.py +# +# Licensed to the Apache Software Foundation (ASF) under one or more +# contributor license agreements. See the NOTICE file distributed with +# this work for additional information regarding copyright ownership. The +# ASF licenses this file to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance with the +# License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# +############################################################################ + +categories = { + "l0-100": lambda mb: mb.block_size() <= 100, + "l100-500": lambda mb: mb.block_size() <= 500, + "l500_1000": lambda mb: mb.block_size() <= 1000, + "l1000_2000": lambda mb: mb.block_size() <= 2000, + "l2000_4000": lambda mb: mb.block_size() <= 4000, + "l4000+": lambda mb: True, +} diff --git a/tools/pynuttx/nxgdb/memclassifier/utils.py b/tools/pynuttx/nxgdb/memclassifier/utils.py new file mode 100644 index 00000000000..8ffb6635074 --- /dev/null +++ b/tools/pynuttx/nxgdb/memclassifier/utils.py @@ -0,0 +1,41 @@ +############################################################################ +# tools/pynuttx/nxgdb/memclassifier/utils.py +# +# Licensed to the Apache Software Foundation (ASF) under one or more +# contributor license agreements. See the NOTICE file distributed with +# this work for additional information regarding copyright ownership. The +# ASF licenses this file to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance with the +# License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# +############################################################################ + + +def backtrace_function_name_judge(funcList, cmp): + def judger(mb): + for funcname, filename in mb.backtrace(): + if any(cmp(funcname, func) for func in funcList): + return True + return False + + return judger + + +def backtrace_function_name_startswith(funcList): + return backtrace_function_name_judge(funcList, lambda x, y: x.startswith(y)) + + +def backtrace_function_name_equal(funcList): + return backtrace_function_name_judge(funcList, lambda x, y: x == y) + + +def backtrace_function_name_contain(funcList): + return backtrace_function_name_judge(funcList, lambda x, y: y in x) diff --git a/tools/pynuttx/nxgdb/memclassify.py b/tools/pynuttx/nxgdb/memclassify.py new file mode 100644 index 00000000000..a3a48720ff0 --- /dev/null +++ b/tools/pynuttx/nxgdb/memclassify.py @@ -0,0 +1,374 @@ +############################################################################ +# tools/gdb/nuttxgdb/memclassify.py +# +# Licensed to the Apache Software Foundation (ASF) under one or more +# contributor license agreements. See the NOTICE file distributed with +# this work for additional information regarding copyright ownership. The +# ASF licenses this file to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance with the +# License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# +############################################################################ +import argparse +import os +import sys + +import gdb + +from . import memdump, mm, utils + + +class Classifier: + def __init__(self, info, category_name=""): + self.stats = [] + self.judgers = [] + self.class_name = category_name + + for key, sub_info in info.items(): + if callable(sub_info): + self.judgers.append(sub_info) + sub_classifier = None + else: # sub_info is a dict + self.judgers.append(sub_info["judger"]) + sub_classifier = ( + Classifier( + sub_info["subcategories"], "_".join([category_name, key]) + ) + if "subcategories" in sub_info + else None + ) + + self.stats.append(MemoryCategory(key, sub_classifier)) + + def __call__(self, mem_blocks): + for mb in mem_blocks: + cat = next( + (idx for idx, method in enumerate(self.judgers) if method(mb)), + None, + ) + + if cat is None: + cat = len(self.stats) + self.stats.append(MemoryCategory(category="unknown")) + self.judgers.append(lambda x: True) + self.stats[cat].append(mb) + for stat in self.stats: + stat.classify() + return self.stats + + +class MemBlock: + def __init__(self): + pass + + def total_size(self): + pass + + def total_size_without_overhead(self): + pass + + def count(self): + pass + + def block_size(self): + pass + + def overhead_size(self): + pass + + def pid(self): + pass + + def backtrace(self): + pass + + def print(self, f=sys.stdout): + def pprint(*args): + print(*args, file=f) + + pprint( + f"pid: {self.pid()}, size: {self.total_size()} = {self.block_size()} x {self.count()}" + ) + + for name, pos in self.backtrace(): + pprint(f"{name:<50} {pos}") + pprint("") + + +class MemoryCategory: + WIDTH = 88 + + def __init__(self, category="total", classifier=None): + self.category = category + self.mem_blocks = [] + self.classifier = classifier + self.children = [] + + def append(self, mem_block): + self.mem_blocks.append(mem_block) + + def extend(self, mem_blocks): + self.mem_blocks.extend(mem_blocks) + + def classify(self): + if self.classifier is None: + return + self.children = self.classifier(self.mem_blocks) + + def summarize(self): + for child in self.children: + child.summarize() + + self.total_mem_size = sum(mb.total_size() for mb in self.mem_blocks) + self.no_overhead_size = sum( + mb.total_size_without_overhead() for mb in self.mem_blocks + ) + self.mem_block_unique_cnt = len(self.mem_blocks) + self.mem_block_cnt = sum(mb.count() for mb in self.mem_blocks) + + def print_statistics(self, categorys=[]): + + if not self.children: + # no children means no categories, just print nothing + return + + categorys.append(self.category) + + def formatter( + name, total_mem_size, total_mem_cnt1, total_mem_cnt2, mem_rm_bt=0 + ): + print( + f"{name:<15}| {total_mem_size:<15}| {total_mem_cnt1:<15}| {total_mem_cnt2:<15}| {mem_rm_bt:<15}" + ) + + title = f"{'.'.join(categorys)} Mem Statistics".center(self.WIDTH, "-") + print(title) + formatter( + "category", + "total mem size", + "memblk uniq cnt", + "memblk tot cnt", + "mem without overhead", + ) + print("-" * self.WIDTH) + for child in self.children: + formatter( + child.category, + child.total_mem_size, + child.mem_block_unique_cnt, + child.mem_block_cnt, + child.no_overhead_size, + ) + + formatter( + "total", + self.total_mem_size, + self.mem_block_unique_cnt, + self.mem_block_cnt, + self.no_overhead_size, + ) + print("-" * self.WIDTH) + for child in self.children: + child.print_statistics() + categorys.pop() + + def collect_piedata(self, title_path=[]): + title_path.append(self.category) + res = [] + if self.children: + res.append( + ( + ".".join(title_path), + [child.category for child in self.children], + [child.no_overhead_size for child in self.children], + ) + ) + for child in self.children: + res.extend(child.collect_piedata(title_path)) + title_path.pop() + return res + + def dump_category(self, output_dir, parentCat=None): + os.makedirs(output_dir, exist_ok=True) + + for child in self.children: + arr = sorted(child.mem_blocks, key=lambda x: x.total_size(), reverse=True) + outputfile = ( + parentCat + f"_{child.category}" if parentCat else child.category + ) + with open(os.path.join(output_dir, outputfile + ".bt"), "w") as f: + print(f"{child.category}, count={len(child.mem_blocks)}", file=f) + for mb in arr: + mb.print(f) + child.dump_category(output_dir, outputfile) + + +def draw_pie(stat): + datasets = stat.collect_piedata() + plt = utils.import_check( + "matplotlib.pyplot", errmsg="Please pip install matplotlib" + ) + if plt is None: + print("matplotlib is not installed") + return + + num_plots = len(datasets) + fig, axs = plt.subplots( + 1, num_plots, figsize=(12, 6), subplot_kw=dict(aspect="equal") + ) + if num_plots == 1: + axs = [axs] + + for i, (title, labels, sizes) in enumerate(datasets): + temp = [x for x in filter(lambda x: x[1], zip(labels, sizes))] + if len(temp) > 0: + labels, sizes = zip(*temp) + else: + continue + axs[i].pie(sizes, labels=labels, autopct="%1.1f%%") + axs[i].set_title(title) + plt.tight_layout() + plt.show() + + +class MemBlockCoredump(MemBlock): + def __init__(self, node, cnt): + super().__init__() + self.mem_node = node + self.cnt = cnt + # deal with call_stack + self.call_stack = [] + for addr, func, file in utils.Backtrace(node.backtrace).backtrace: + func = func.strip("<>") + if func.find("+"): # remove the offset affter '+' + func = func[: func.find("+")] + self.call_stack.append((func, file)) + + def total_size(self): + return self.mem_node.nodesize * self.cnt + + def total_size_without_overhead(self): + return (self.mem_node.nodesize - self.mem_node.overhead) * self.cnt + + def count(self): + return self.cnt + + def block_size(self): + return self.mem_node.nodesize + + def overhead_size(self): + return self.mem_node.overhead + + def pid(self): + return self.mem_node.pid + + def backtrace(self): + return self.call_stack + + +class MMClassify(gdb.Command): + """classify memory by callstack""" + + def __init__(self): + super().__init__("mm classify", gdb.COMMAND_USER) + utils.alias("memclassify", "mm classify") + + def parse_args(self, argv): + parser = argparse.ArgumentParser(description="Memory Classify") + parser.add_argument( + "-o", + "--output-dir", + default="memclass.output", + help="Specify the directory to save the the call stack files after categorization", + ) + + parser.add_argument( + "-p", "--pid", type=int, default=None, help="Thread PID, -1 for mempool" + ) + + parser.add_argument( + "-c", + "--classifier-file", + default="default", + help="Specify the config file. Default is 'script_path/default.py'", + ) + + parser.add_argument( + "-l", + "--log", + default=None, + help="Specify the memdump log file.", + ) + + try: + args = parser.parse_args(argv) + except SystemExit: + return False + + return args + + def invoke(self, arg: str, from_tty: bool) -> None: + if not (args := self.parse_args(gdb.string_to_argv(arg))): + print("memoryclassify: parse args error") + return + + def import_classify_config(classifier_file): + classifier_dir = os.path.join(os.path.dirname(__file__), "memclassifier") + sys.path.append(classifier_dir) + return utils.import_reload( + classifier_file, + errmsg=f"Please provide {classifier_file}.py in {classifier_dir}\n", + ) + + classify_config = import_classify_config(args.classifier_file) + if not classify_config: + return + + memblocks = [] + if args.log: # get mem block from memdump log + memblocks.extend( + MemBlockCoredump(node, 1) + for node in memdump.parse_memdump_log(args.log) + ) + else: + if not mm.CONFIG_MM_BACKTRACE or mm.CONFIG_MM_BACKTRACE < 8: + print("memoryclassify: no backtrace") + return + + filters = { + "pid": args.pid, + "nodesize": None, + "used": None, + "free": None, + "seqmin": None, + "seqmax": None, + "orphan": None, + "no_heap": None, + "no_pool": None, + "no_pid": None, + } + + memblocks.extend( + MemBlockCoredump(node, len(nodes)) + for node, nodes in memdump.group_nodes( + memdump.dump_nodes(mm.get_heaps(), filters) + ).items() + ) + + stat = MemoryCategory( + "total", Classifier(getattr(classify_config, "categories")) + ) + stat.extend(memblocks) + stat.classify() + stat.summarize() + stat.print_statistics() + stat.dump_category(args.output_dir) + draw_pie(stat) diff --git a/tools/pynuttx/nxgdb/utils.py b/tools/pynuttx/nxgdb/utils.py index 435abfd1526..3fc1aa7199f 100644 --- a/tools/pynuttx/nxgdb/utils.py +++ b/tools/pynuttx/nxgdb/utils.py @@ -30,6 +30,7 @@ import math import os import re import shlex +import sys from enum import Enum from typing import List, Optional, Tuple, Union @@ -501,13 +502,26 @@ def get_bytes(val, size): def import_check(module, name="", errmsg=""): try: module = __import__(module, fromlist=[name]) - except ImportError: + except ImportError as e: + gdb.write(f"import_error: {e}\n") gdb.write(errmsg if errmsg else f"Error to import {module}\n") return None return getattr(module, name) if name else module +def import_reload(module, name="", errmsg=""): + """Clear and reload the module from sys.modules""" + if module in sys.modules: + module = importlib.reload(sys.modules[module]) + else: + module = import_check( + module, + errmsg=errmsg, + ) + return module + + def hexdump(address, size): address = int(address) inf = gdb.inferiors()[0] -- Gitee From 36ba5ac3938311fdfbe894362d916c4a776776ad Mon Sep 17 00:00:00 2001 From: anjiahao Date: Mon, 17 Feb 2025 17:13:54 +0800 Subject: [PATCH 106/235] elf: Add `elfimport` command to load ELF symbols for debugging VELAPLATFO-53891 Implement `elfimport` command to load ELF files for debugging purposes. If the current environment has already loaded an ELF, this command will work seamlessly. The command supports specifying a directory (e.g., `elfimport ../apps/bin`), where it will attempt to load ELF files in the specified path. ELF files whose filenames match the module name (`mod.name`) will be automatically loaded. Change-Id: I20358b5905c14126df3ba6c8b455c6f42780acde Signed-off-by: anjiahao --- binfmt/elf.c | 8 ++++ tools/pynuttx/nxgdb/elf.py | 87 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 95 insertions(+) create mode 100644 tools/pynuttx/nxgdb/elf.py diff --git a/binfmt/elf.c b/binfmt/elf.c index 433cadc8d52..57cf8e40b46 100644 --- a/binfmt/elf.c +++ b/binfmt/elf.c @@ -225,6 +225,14 @@ static int elf_loadbinary(FAR struct binary_s *binp, } #endif +#ifdef HAVE_MODLIB_NAMES + /* Save the filename in the registry entry */ + + strlcpy(binp->mod.modname, strrchr(filename, '/') == NULL ? + filename: strrchr(filename, '/') + 1, + sizeof(binp->mod.modname)); +#endif + modlib_uninitialize(&loadinfo); return OK; diff --git a/tools/pynuttx/nxgdb/elf.py b/tools/pynuttx/nxgdb/elf.py new file mode 100644 index 00000000000..2c9227f9955 --- /dev/null +++ b/tools/pynuttx/nxgdb/elf.py @@ -0,0 +1,87 @@ +############################################################################ +# tools/pynuttx/nxgdb/elf.py +# +# SPDX-License-Identifier: Apache-2.0 +# +# Licensed to the Apache Software Foundation (ASF) under one or more +# contributor license agreements. See the NOTICE file distributed with +# this work for additional information regarding copyright ownership. The +# ASF licenses this file to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance with the +# License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# +############################################################################ + +import argparse +import os + +import gdb + +try: + import lief +except ImportError: + print('Package missing, please do "pip install lief"') + +from .utils import get_field_nitems, get_tcbs + +CONFIG_ARCH_USE_SEPARATED_SECTION = get_field_nitems("struct module_s", "sectalloc") + + +class ElfImport(gdb.Command): + def __init__(self): + super().__init__("elfimport", gdb.COMMAND_USER) + + def invoke(self, args, from_tty): + parser = argparse.ArgumentParser(description="import elf symbols to gdb") + parser.add_argument("elfpath", type=str, help="elf file path, etc: apps/bin") + try: + args = parser.parse_args(args.split()) + except SystemExit: + return None + + tcbs = get_tcbs() + if tcbs is None: + print("No TCBs found") + return + bins = [] + for tcb in tcbs: + if tcb["group"] != 0 and tcb["group"]["tg_bininfo"] != 0: + bins.append(tcb["group"]["tg_bininfo"]) + + if len(bins) == 0: + print("Not find elf in current environment") + return + + print(f"Have {len(bins)} elf in current environment") + + for i, bin in enumerate(bins): + mod = bin["mod"] + sections = {} + cmd = "" + if CONFIG_ARCH_USE_SEPARATED_SECTION: + for i in range(mod["nsect"]): + section = hex(mod["sectalloc"][i]) + if section != "0x0": + sections[i] = section + filename = os.path.join(args.elfpath, mod["modname"].string()) + cmd = f"add-symbol-file {filename} " + elf = lief.parse(filename) + for i, section in sections.items(): + cmd += f"-s {elf.sections[i].name} {sections[i]} " + else: + filename = os.path.join(args.elfpath, mod["modname"].string()) + cmd = f"add-symbol-file {filename} -s .text {hex(mod['textalloc'])} -s .data {hex(mod['dataalloc'])}" + + print(cmd) + gdb.execute(cmd) + + +ElfImport() -- Gitee From c32a51d25ad3bfab192740a3261aad91ae5440be Mon Sep 17 00:00:00 2001 From: xuxingliang Date: Fri, 14 Feb 2025 17:55:08 +0800 Subject: [PATCH 107/235] nxgdb: fix diagnose report exception VELAPLATFO-53324 It's possible the sub command generate any kinds of exception aside from gdb.error, capture them all. Change-Id: Id381fc65b35c0d7813831f730a87a9e277e1e77c Signed-off-by: xuxingliang --- tools/pynuttx/nxgdb/diagnose.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/pynuttx/nxgdb/diagnose.py b/tools/pynuttx/nxgdb/diagnose.py index 0a0f694fb44..28fd334351e 100644 --- a/tools/pynuttx/nxgdb/diagnose.py +++ b/tools/pynuttx/nxgdb/diagnose.py @@ -74,7 +74,7 @@ class DiagnoseReport(gdb.Command): gdb.write(f"Run command: {name}\n") try: result = command.diagnose() - except gdb.error as e: + except Exception as e: result = { "title": f"Command {name} failed", "summary": "Command execution failed", -- Gitee From 05913dc20bb399c8589de33b2317ab7991fa02e2 Mon Sep 17 00:00:00 2001 From: anjiahao Date: Tue, 18 Feb 2025 17:44:46 +0800 Subject: [PATCH 108/235] pygdb/elf.py:Improve code implementation VELAPLATFO-53891 Change-Id: I03b624f49b45075725c07b941fe66391b71c7c38 Signed-off-by: anjiahao --- tools/pynuttx/nxgdb/elf.py | 39 ++++++++++++------------- tools/pynuttx/nxgdb/protocols/thread.py | 21 ++++++++++++- 2 files changed, 38 insertions(+), 22 deletions(-) diff --git a/tools/pynuttx/nxgdb/elf.py b/tools/pynuttx/nxgdb/elf.py index 2c9227f9955..51d1c142c55 100644 --- a/tools/pynuttx/nxgdb/elf.py +++ b/tools/pynuttx/nxgdb/elf.py @@ -30,14 +30,15 @@ try: except ImportError: print('Package missing, please do "pip install lief"') -from .utils import get_field_nitems, get_tcbs +from .utils import get_tcbs, has_field -CONFIG_ARCH_USE_SEPARATED_SECTION = get_field_nitems("struct module_s", "sectalloc") +CONFIG_ARCH_USE_SEPARATED_SECTION = has_field("struct module_s", "sectalloc") class ElfImport(gdb.Command): def __init__(self): - super().__init__("elfimport", gdb.COMMAND_USER) + if has_field("struct task_group_s", "tg_bininfo"): + super().__init__("elfimport", gdb.COMMAND_USER) def invoke(self, args, from_tty): parser = argparse.ArgumentParser(description="import elf symbols to gdb") @@ -51,37 +52,33 @@ class ElfImport(gdb.Command): if tcbs is None: print("No TCBs found") return - bins = [] + modules = [] for tcb in tcbs: - if tcb["group"] != 0 and tcb["group"]["tg_bininfo"] != 0: - bins.append(tcb["group"]["tg_bininfo"]) + if tcb.group != 0 and tcb.group.tg_bininfo != 0: + modules.append(tcb.group.tg_bininfo.mod) - if len(bins) == 0: - print("Not find elf in current environment") + if not modules: + print("No modules in current environment") return - print(f"Have {len(bins)} elf in current environment") + print(f"Found {len(modules)} modules in current environment") - for i, bin in enumerate(bins): - mod = bin["mod"] + for mod in modules: sections = {} cmd = "" if CONFIG_ARCH_USE_SEPARATED_SECTION: - for i in range(mod["nsect"]): - section = hex(mod["sectalloc"][i]) - if section != "0x0": - sections[i] = section - filename = os.path.join(args.elfpath, mod["modname"].string()) + for i in range(mod.nsect): + section = mod.sectalloc[i] + if section: + sections[i] = hex(section) + filename = os.path.join(args.elfpath, mod.modname.string()) cmd = f"add-symbol-file {filename} " elf = lief.parse(filename) for i, section in sections.items(): cmd += f"-s {elf.sections[i].name} {sections[i]} " else: - filename = os.path.join(args.elfpath, mod["modname"].string()) - cmd = f"add-symbol-file {filename} -s .text {hex(mod['textalloc'])} -s .data {hex(mod['dataalloc'])}" + filename = os.path.join(args.elfpath, mod.modname.string()) + cmd = f"add-symbol-file {filename} -s .text {hex(mod.textalloc)} -s .data {hex(mod.dataalloc)}" print(cmd) gdb.execute(cmd) - - -ElfImport() diff --git a/tools/pynuttx/nxgdb/protocols/thread.py b/tools/pynuttx/nxgdb/protocols/thread.py index 71e970bea8f..45af852cfb5 100644 --- a/tools/pynuttx/nxgdb/protocols/thread.py +++ b/tools/pynuttx/nxgdb/protocols/thread.py @@ -24,6 +24,25 @@ from .fs import FileList from .value import Value +class TgBininfo(Value): + """struct tg_bininfo_s""" + + entrypt: Value + mapped: Value + mod: Value + picbase: Value + addrenv: Value + oldenv: Value + mapsize: Value + priority: Value + stacksize: Value + uid: Value + gid: Value + mode: Value + stackaddr: Value + unload: Value + + class Group(Value): """struct group_s""" @@ -35,7 +54,7 @@ class Group(Value): tg_euid: Value tg_egid: Value tg_members: Value - tg_bininfo: Value + tg_bininfo: TgBininfo tg_children: Value tg_nchildren: Value tg_exitcode: Value -- Gitee From bd00a3392094d1b2040d9d6311a46224c682cd30 Mon Sep 17 00:00:00 2001 From: anjiahao Date: Wed, 19 Feb 2025 14:05:58 +0800 Subject: [PATCH 109/235] pynuttx:remove pthread_tcb_s cast VELAPLATFO-53971 Change-Id: Icfeb59af4696b415bb0bf4b648af914a89e2c4d4 Signed-off-by: anjiahao --- tools/pynuttx/nxgdb/utils.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/tools/pynuttx/nxgdb/utils.py b/tools/pynuttx/nxgdb/utils.py index 3fc1aa7199f..14db8e2e2c0 100644 --- a/tools/pynuttx/nxgdb/utils.py +++ b/tools/pynuttx/nxgdb/utils.py @@ -929,8 +929,7 @@ def get_task_argvstr(tcb: Tcb) -> List[str]: if tcb.flags & TCB_FLAG_TTYPE_MASK == TCB_FLAG_TTYPE_PTHREAD: if tcb.type.code != gdb.TYPE_CODE_PTR: tcb = tcb.address - tcb = tcb.cast(lookup_type("struct pthread_tcb_s").pointer()) - return ["", f"{tcb['cmn']['entry']['main']}", f'{tcb["arg"]}'] + return ["", f"{tcb['entry']['main']}", f'{tcb["arg"]}'] tls_info_s = lookup_type("struct tls_info_s").pointer() tls = tcb.stack_alloc_ptr.cast(tls_info_s) -- Gitee From 79dd3a6c0878a7807c9a87d7cfd146d1a7adb0b5 Mon Sep 17 00:00:00 2001 From: liwenxiang1 Date: Tue, 18 Feb 2025 16:26:31 +0800 Subject: [PATCH 110/235] tools/gdb: Add pginfo.py to gdb plugin VELAPLATFO-54020 Output in the following format: CR3: 0x102000 [PML4 0] -> 0x103000 (RW) [PDPT 0] -> 0x104000 (RW) [PD 0] -> 0x108000 (RW) [PT 224] -> 0xe0000 (RW 4K) Change-Id: I536b21ae183f82a39045c51defcaa671c3922e06 Signed-off-by: liwenxiang1 --- tools/pynuttx/nxgdb/pginfo.py | 119 ++++++++++++++++++++++++++++++++++ 1 file changed, 119 insertions(+) create mode 100644 tools/pynuttx/nxgdb/pginfo.py diff --git a/tools/pynuttx/nxgdb/pginfo.py b/tools/pynuttx/nxgdb/pginfo.py new file mode 100644 index 00000000000..ad21c55f717 --- /dev/null +++ b/tools/pynuttx/nxgdb/pginfo.py @@ -0,0 +1,119 @@ +############################################################################ +# tools/pynuttx/nxgdb/pginfo.py +# +# SPDX-License-Identifier: Apache-2.0 +# +# Licensed to the Apache Software Foundation (ASF) under one or more +# contributor license agreements. See the NOTICE file distributed with +# this work for additional information regarding copyright ownership. The +# ASF licenses this file to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance with the +# License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# +############################################################################ + +import gdb + +from .utils import read_u64 + + +class PageTable: + """Base class for page table handling.""" + + def __init__(self): + pass + + def walk_table(self, base, level, prefix=""): + """Placeholder for architecture-specific table walking logic.""" + raise NotImplementedError("Subclasses must implement this method.") + + def dump(self): + """Placeholder for architecture-specific dumping logic.""" + raise NotImplementedError("Subclasses must implement this method.") + + +class PageTableX86(PageTable): + """x86_64-specific page table walker.""" + + PAGE_SIZE = 4096 + NUM_ENTRIES = 512 + ENTRY_SIZE = 8 + PAGE_PRESENT = 1 << 0 + PAGE_WRITABLE = 1 << 1 + PAGE_PSE = 1 << 7 + + PAGE_LEVELS = {0: "PML4", 1: "PDPT", 2: "PD", 3: "PT"} + PAGE_SIZES = {1: "1G", 2: "2M", 3: "4K"} + + def __init__(self): + super().__init__() + + def walk_table(self, base, level, prefix=""): + """x86_64-specific implementation to traverse the page table and yield entries.""" + if level > 3: + return + + table_name = self.PAGE_LEVELS.get(level, f"L{level}") + for i in range(self.NUM_ENTRIES): + entry_addr = base + i * self.ENTRY_SIZE + 0x100000000 + data = gdb.selected_inferior().read_memory(entry_addr, self.ENTRY_SIZE) + entry = read_u64(data, 0) + + if not (entry & self.PAGE_PRESENT): + continue + + addr = entry & ~0xFFF + flags = "RW" if entry & self.PAGE_WRITABLE else "R" + if level == 3 or (level in (2, 1) and entry & self.PAGE_PSE): + size = self.PAGE_SIZES.get(level, "") + else: + size = "" + + if size: + line = f"{prefix}[{table_name} {i}] -> {addr:#x} ({flags} {size})" + else: + line = f"{prefix}[{table_name} {i}] -> {addr:#x} ({flags})" + yield line + + if level < 3 and not (level in (2, 1) and entry & self.PAGE_PSE): + yield from self.walk_table(addr, level + 1, prefix + " ") + + if level == 0: + break + + def dump(self): + pml4_addr = int(gdb.parse_and_eval("&pml4")) & ~0xFFF + print(f"pml4_addr: {pml4_addr:#x}") + + for line in self.walk_table(pml4_addr, 0): + print(line) + + +class DumpPageTableCommand(gdb.Command): + """GDB command to dump page tables based on architecture.""" + + def __init__(self): + super().__init__("dump_pagetable", gdb.COMMAND_USER) + + def invoke(self, arg, from_tty): + + arch = gdb.selected_inferior().architecture().name() + arch_classes = { + "i386:x86-64": PageTableX86, # Add other architectures as needed + } + + clz = arch_classes.get(arch) + if not clz: + print(f"Unsupported architecture: {arch}") + return + + pagetable = clz() + pagetable.dump() -- Gitee From c0eccd7e6079b6eaea63124879967fe49ebe28d0 Mon Sep 17 00:00:00 2001 From: chenzhijia Date: Fri, 21 Feb 2025 09:44:12 +0800 Subject: [PATCH 111/235] nxgdb/utils.py:Fix source gdbinit.py script error report VELAPLATFO-54243 Registering NuttX GDB commands from /home/mi/code/stable_oh2/nuttx/tools/pynuttx/nxgdb set pagination off set python print-stack full "handle SIGUSR1 "nostop" "pass" "noprint" Load macro: /tmp/6024dea73606400ae39a7b7da42cecbf.json Please pip install debugpyIgnore module: elf, error: 'NoneType' object has no attribute 'code' Traceback (most recent call last): File "/home/mi/code/stable_oh2/nuttx/tools/pynuttx/nxgdb/_init_.py", line 54, in init_gdb_commands module = importlib.import_module(f"{_package_}.{m}") File "/usr/lib/python3.10/importlib/_init_.py", line 126, in import_module return _bootstrap._gcd_import(name[level:], package, level) File "", line 1050, in _gcd_import File "", line 1027, in _find_and_load File "", line 1006, in _find_and_load_unlocked File "", line 688, in _load_unlocked File "", line 883, in exec_module File "", line 241, in _call_with_frames_removed File "/home/mi/code/stable_oh2/nuttx/tools/pynuttx/nxgdb/elf.py", line 35, in CONFIG_ARCH_USE_SEPARATED_SECTION = has_field("struct module_s", "sectalloc") File "/home/mi/code/stable_oh2/nuttx/tools/pynuttx/nxgdb/utils.py", line 488, in has_field return get_type_field(obj, field) is not None File "/home/mi/code/stable_oh2/nuttx/tools/pynuttx/nxgdb/utils.py", line 267, in get_type_field while t.code in (gdb.TYPE_CODE_PTR, gdb.TYPE_CODE_ARRAY, gdb.TYPE_CODE_TYPEDEF): AttributeError: 'NoneType' object has no attribute 'code' No symbol g_version found in memory, skipping version check Change-Id: I60cbcff86dbd0214bc12acca1a5614b87f587088 Signed-off-by: chenzhijia --- tools/pynuttx/nxgdb/utils.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/tools/pynuttx/nxgdb/utils.py b/tools/pynuttx/nxgdb/utils.py index 14db8e2e2c0..0f93f19d9df 100644 --- a/tools/pynuttx/nxgdb/utils.py +++ b/tools/pynuttx/nxgdb/utils.py @@ -265,6 +265,9 @@ def get_type_field(obj: Union[TypeOrStr, gdb.Value], field: str) -> gdb.Field: else: raise gdb.GdbError(f"Unsupported type {type(obj)}") + if not t: + return None + while t.code in (gdb.TYPE_CODE_PTR, gdb.TYPE_CODE_ARRAY, gdb.TYPE_CODE_TYPEDEF): t = t.target() -- Gitee From de76cbad9c3bd3ff0d298b0740c3e339d2e31e58 Mon Sep 17 00:00:00 2001 From: Bowen Wang Date: Thu, 20 Feb 2025 22:52:02 +0800 Subject: [PATCH 112/235] nxgdb/rpmsg.py: update the rpmsg.py after change the struct rpmsg_s VELAPLATFO-53593 rdev has been remove in struct rpmsg_s and now we need use: struct rpmsg_device *rdev = (struct rpmsg_device *)(rpmsg + 1) to get the rdev. Change-Id: I8a857e44e5dcffba790e2e526aefc77aea308029 Signed-off-by: Bowen Wang --- tools/pynuttx/nxgdb/rpmsg.py | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/tools/pynuttx/nxgdb/rpmsg.py b/tools/pynuttx/nxgdb/rpmsg.py index e92e891ac06..b976620a3e6 100644 --- a/tools/pynuttx/nxgdb/rpmsg.py +++ b/tools/pynuttx/nxgdb/rpmsg.py @@ -224,11 +224,13 @@ class RPMsgDump(gdb.Command): def dump_rpmsg(self, transport_only): for rpmsg in NxList(gdb.parse_and_eval("g_rpmsg"), "struct rpmsg_s", "node"): - gdb.write(f"Rpmsg Device: rpmsg:{rpmsg} rdev:{rpmsg['rdev']}\n") + rdev = utils.Value(int(rpmsg) + utils.sizeof("struct rpmsg_s")) + rdev = rdev.cast(utils.lookup_type("struct rpmsg_device").pointer()) + gdb.write(f"Rpmsg Device: rpmsg:{rpmsg} rdev:{rdev}\n") if not transport_only: - self.dump_rdev(rpmsg["rdev"]) - self.dump_rpmsg_virtio(rpmsg["rdev"]) - self.dump_rpmsg_port(rpmsg["rdev"]) + self.dump_rdev(rdev) + self.dump_rpmsg_virtio(rdev) + self.dump_rpmsg_port(rdev) def invoke(self, args, from_tty): if not (args := self.parse_args(args)): -- Gitee From 8de48ad6b02b146220afba29593b82f87675e576 Mon Sep 17 00:00:00 2001 From: Bowen Wang Date: Thu, 20 Feb 2025 22:54:12 +0800 Subject: [PATCH 113/235] nxgdb/rpmsg.py: optimize the rpmsg transport judge logic VELAPLATFO-54239 python script will report error when call the dump_rpmsg_port() when rpmsg port is not enabled in NuttX because the symbol "rpmsg_port_get_tx_payload_buffer" can't be found. Optimize the rpmsg transport judge logic and fix above BUG. Change-Id: I27244352b6538ea3ba037ccb78c8631d3a36ef9b Signed-off-by: Bowen Wang --- tools/pynuttx/nxgdb/rpmsg.py | 29 +++++++++++++++++++---------- 1 file changed, 19 insertions(+), 10 deletions(-) diff --git a/tools/pynuttx/nxgdb/rpmsg.py b/tools/pynuttx/nxgdb/rpmsg.py index b976620a3e6..ccf5f8a9fdc 100644 --- a/tools/pynuttx/nxgdb/rpmsg.py +++ b/tools/pynuttx/nxgdb/rpmsg.py @@ -80,6 +80,22 @@ class RPMsgDump(gdb.Command): except SystemExit: return + def is_rpmsg_transport(self, rdev, transport): + if transport == "virtio": + tx_payload = "rpmsg_virtio_get_tx_payload_buffer" + elif transport == "port": + tx_payload = "rpmsg_port_get_tx_payload_buffer" + else: + return False + + symbol = gdb.lookup_symbol(tx_payload) + if symbol[0] is None: + return False + + real_addr = symbol[0].value().address + ops_addr = int(utils.Value(rdev["ops"]["get_tx_payload_buffer"])) & ~1 + return real_addr == ops_addr + def dump_virtqueue(self, vq): vr = vq["vq_ring"] gdb.write( @@ -101,11 +117,7 @@ class RPMsgDump(gdb.Command): ) def dump_rpmsg_virtio(self, rdev): - real_addr = hex( - gdb.lookup_symbol("rpmsg_virtio_get_tx_payload_buffer")[0].value().address - ) - ops_addr = hex(int(utils.Value(rdev["ops"]["get_tx_payload_buffer"])) & ~1) - if real_addr != ops_addr: + if not self.is_rpmsg_transport(rdev, "virtio"): return rvdev = rdev.cast(utils.lookup_type("struct rpmsg_virtio_device").pointer()) @@ -156,12 +168,9 @@ class RPMsgDump(gdb.Command): return buffer_list def dump_rpmsg_port(self, rdev): - real_addr = hex( - gdb.lookup_symbol("rpmsg_port_get_tx_payload_buffer")[0].value().address - ) - ops_addr = hex(int(utils.Value(rdev["ops"]["get_tx_payload_buffer"])) & ~1) - if real_addr != ops_addr: + if not self.is_rpmsg_transport(rdev, "port"): return + port = rdev.cast(utils.lookup_type("struct rpmsg_port_s").pointer()) gdb.write(f"rxq nused:{port['rxq']['ready']['num']}\n") -- Gitee From 9ff6c5ea6b72004a390f4f3ff47ba8fc808f93d7 Mon Sep 17 00:00:00 2001 From: ganjing Date: Wed, 26 Feb 2025 13:41:31 +0800 Subject: [PATCH 114/235] feat: uname GDB Plugin Implementation VELAPLATFO-54649 Change-Id: I03313aedee70f7a377ecbbfadec6ffac1a8961b2 Signed-off-by: ganjing --- tools/pynuttx/nxgdb/uname.py | 120 +++++++++++++++++++++++++++++++++++ 1 file changed, 120 insertions(+) create mode 100644 tools/pynuttx/nxgdb/uname.py diff --git a/tools/pynuttx/nxgdb/uname.py b/tools/pynuttx/nxgdb/uname.py new file mode 100644 index 00000000000..fc8a3e156a5 --- /dev/null +++ b/tools/pynuttx/nxgdb/uname.py @@ -0,0 +1,120 @@ +############################################################################ +# tools/pynuttx/nxgdb/uname.py +# +# Licensed to the Apache Software Foundation (ASF) under one or more +# contributor license agreements. See the NOTICE file distributed with +# this work for additional information regarding copyright ownership. The +# ASF licenses this file to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance with the +# License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# +############################################################################ + +import argparse + +import gdb + +from . import utils + + +class UnameCommand(gdb.Command): + """Output specific system information""" + + def __init__(self): + super().__init__("uname", gdb.COMMAND_USER) + + def parse_arguments(self, argv): + parser = argparse.ArgumentParser(description=self.__doc__) + parser.add_argument( + "-a", + "--all", + action="store_true", + help="Output all information in the following order", + ) + parser.add_argument( + "-s", "--kernel-name", action="store_true", help="Output the kernel name" + ) + parser.add_argument( + "-n", + "--nodename", + action="store_true", + help="Output the hostname of the network node", + ) + parser.add_argument( + "-r", + "--kernel-release", + action="store_true", + help="Output the kernel release number", + ) + parser.add_argument( + "-v", + "--kernel-version", + action="store_true", + help="Output the kernel version number", + ) + parser.add_argument( + "-m", + "--machine", + action="store_true", + help="Output the hardware architecture name of the host", + ) + parser.add_argument( + "--version", + action="store_true", + help="Display version information and exit", + ) + + try: + args = parser.parse_args(argv) + except SystemExit: + return None + + return args + + def invoke(self, args, from_tty): + + args = self.parse_arguments(gdb.string_to_argv(args)) + if not args: + return + + kernel_name = "NuttX" + node_name = str(utils.get_symbol_value("CONFIG_LIBC_HOSTNAME") or "").replace( + '"', "" + ) + kernel_release = str( + utils.get_symbol_value("CONFIG_VERSION_STRING") or "" + ).replace('"', "") + kernel_version = str(utils.parse_and_eval("g_version") or "").replace('"', "") + machine = str(utils.get_symbol_value("CONFIG_ARCH") or "").replace('"', "") + tool_version = "1.0.0" + + if args.all: + print( + kernel_name, + node_name, + kernel_release, + kernel_version, + machine, + tool_version, + ) + return + if args.kernel_name: + print(kernel_name) + if args.nodename: + print(node_name) + if args.kernel_release: + print(kernel_release) + if args.kernel_version: + print(kernel_version) + if args.machine: + print(machine) + if args.version: + print(tool_version) -- Gitee From 19163f6a3953cdab315252f4554b08575517f43e Mon Sep 17 00:00:00 2001 From: xuxingliang Date: Fri, 28 Feb 2025 09:35:53 +0800 Subject: [PATCH 115/235] nxgdb/mm: optimize memdump command VELAPLATFO-54531 1. Use NodeSize in header to avoid misunderstanding of totalsize(count * nodesize) 2. Support an arbitrary expression as heap parameter, E.g. --heap 0x1234 or --heap g_mmheap Change-Id: I376e04d4c57e346a80e7eb31ccccf808616716a7 Signed-off-by: xuxingliang --- tools/pynuttx/nxgdb/memdump.py | 2 +- tools/pynuttx/nxgdb/mm.py | 7 +++++++ 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/tools/pynuttx/nxgdb/memdump.py b/tools/pynuttx/nxgdb/memdump.py index 77a7c5ccd14..a806b93110a 100644 --- a/tools/pynuttx/nxgdb/memdump.py +++ b/tools/pynuttx/nxgdb/memdump.py @@ -137,7 +137,7 @@ def print_header(formatter=None): "Pool", "CNT", "PID", - "Size", + "NodeSize", "Overhead", "Seqno", "Address", diff --git a/tools/pynuttx/nxgdb/mm.py b/tools/pynuttx/nxgdb/mm.py index eb90d5d86aa..a26bbe33876 100644 --- a/tools/pynuttx/nxgdb/mm.py +++ b/tools/pynuttx/nxgdb/mm.py @@ -528,8 +528,15 @@ class MMHeap(Value, p.MMHeap): """ def __init__(self, heap: Value, name=None) -> None: + mm_heap_s = utils.lookup_type("struct mm_heap_s") if heap.type.code == gdb.TYPE_CODE_PTR: heap = heap.dereference() + elif heap.type.code == gdb.TYPE_CODE_INT: + heap = gdb.Value(heap).cast(mm_heap_s.pointer()).dereference() + + if heap.type != mm_heap_s: + raise ValueError(f"Invalid heap type: {heap.type}") + super().__init__(heap) self.name = name or "" -- Gitee From 352840ac23fd1c6a415ce8b32fbfb9ba34d65131 Mon Sep 17 00:00:00 2001 From: xuxingliang Date: Mon, 24 Feb 2025 22:12:24 +0800 Subject: [PATCH 116/235] pynuttx: reload all pynuttx modules in gdbinit.py VELAPLATFO-53324 Make it easy to develop pynuttx code, by source gdbinit.py again from GDB will reload all modules and make the changes take effect immediately. Change-Id: I08c3f7b434a92d38be0e4404f653e361be29a3dc Signed-off-by: xuxingliang --- tools/pynuttx/gdbinit.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/tools/pynuttx/gdbinit.py b/tools/pynuttx/gdbinit.py index a965fa34850..440acb89baf 100644 --- a/tools/pynuttx/gdbinit.py +++ b/tools/pynuttx/gdbinit.py @@ -29,9 +29,9 @@ if __name__ == "__main__": if here not in sys.path: sys.path.insert(0, here) - if "nxgdb" in sys.modules: - for key in list(sys.modules.keys()): - if key.startswith("nxgdb"): - del sys.modules[key] + modules = ("nxelf", "nxgdb", "nxreg", "nxstub", "nxtrace") + for key in list(sys.modules): + if key.startswith(modules): + del sys.modules[key] import nxgdb # noqa: F401 -- Gitee From 26cfa6e6b9d97f413388d9aeb301d95faa44ec66 Mon Sep 17 00:00:00 2001 From: yangao1 Date: Tue, 4 Mar 2025 10:43:53 +0800 Subject: [PATCH 117/235] nxreg/register.py:modify struct reginfo,add reserved member VELAPLATFO-52907 Change-Id: I98a0589ce9060fc554335a4b2755d6d6c3751c53 Signed-off-by: yangao1 --- tools/pynuttx/nxreg/register.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/tools/pynuttx/nxreg/register.py b/tools/pynuttx/nxreg/register.py index a2ae4a1f47b..835ae739c98 100644 --- a/tools/pynuttx/nxreg/register.py +++ b/tools/pynuttx/nxreg/register.py @@ -22,7 +22,7 @@ import logging from binascii import hexlify from typing import List, Union -from construct import Array, Int8ul, Int16ul, PaddedString, Struct +from construct import Array, Int8ul, Int16sl, Int16ul, PaddedString, Struct from nxelf.elf import LiefELF UINT16_MAX = 0xFFFF @@ -304,8 +304,9 @@ def get_reginfo(elf: LiefELF) -> List[RegInfo]: "name" / PaddedString(8, "utf-8"), "size" / Int8ul, "regnum" / Int8ul, - "toffset" / Int16ul, - "goffset" / Int16ul, + "toffset" / Int16sl, + "goffset" / Int16sl, + "reserved" / Int16ul, ) regsnum = len(data) // reginfo_s.sizeof() -- Gitee From 1757255b0dfbff128a2bb0b1ef271cff9ea29585 Mon Sep 17 00:00:00 2001 From: ganjing Date: Wed, 5 Mar 2025 10:51:55 +0800 Subject: [PATCH 118/235] nxgdb/utils.py: Change the return value type of "container_of" from gdb.Value to Value VELAPLATFO-55216 Change-Id: I6d7efb451e9745e32e729a749c5afe19fed321d7 Signed-off-by: ganjing --- tools/pynuttx/nxgdb/utils.py | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/tools/pynuttx/nxgdb/utils.py b/tools/pynuttx/nxgdb/utils.py index 0f93f19d9df..e75bea23932 100644 --- a/tools/pynuttx/nxgdb/utils.py +++ b/tools/pynuttx/nxgdb/utils.py @@ -310,9 +310,7 @@ def offset_of(typeobj: TypeOrStr, field: str) -> Union[int, None]: raise gdb.GdbError(f"Field {field} not found in type {typeobj}") -def container_of( - ptr: Union[gdb.Value, int], typeobj: TypeOrStr, member: str -) -> gdb.Value: +def container_of(ptr: Union[Value, int], typeobj: TypeOrStr, member: str) -> Value: """ Return a pointer to the containing data structure. @@ -322,7 +320,7 @@ def container_of( member: Name of the member in the container. Returns: - gdb.Value of the container. + Value of the container. Example: struct foo { @@ -333,13 +331,13 @@ def container_of( """ if isinstance(typeobj, str): - typeobj = gdb.lookup_type(typeobj).pointer() + typeobj = lookup_type(typeobj).pointer() if typeobj.code is not gdb.TYPE_CODE_PTR: typeobj = typeobj.pointer() - addr = gdb.Value(ptr).cast(long_type) - return gdb.Value(addr - offset_of(typeobj, member)).cast(typeobj) + addr = Value(ptr).cast(long_type) + return Value(addr - offset_of(typeobj, member)).cast(typeobj) class ContainerOf(gdb.Function): -- Gitee From 8f29dcb74625c6600c6df5f9fa866478eae48c0f Mon Sep 17 00:00:00 2001 From: ganjing Date: Fri, 28 Feb 2025 19:32:19 +0800 Subject: [PATCH 119/235] feat: tlsdump GDB Plugin Implementation VELAPLATFO-54923 usage: (gdb) tlsdump -p PID example: 1. Dump all task tls info: (gdb)tlsdump Output: PID:48, TASK, task_info addr:0x9f009dc8 *task tls elements: 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 *thread tls elements: 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 PID:49, PTHREAD, task_info addr:0x9f006dc8 *thread tls elements: 0x0 0xf519c8b0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 2. Dump the tls info of the thread/task represented by this pid (gdb)tlsdump -p pid Output: PID:49, PTHREAD, task_info addr:0x9f006dc8 *thread tls elements: 0x0 0xf519c8b0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 3. Do integrity check (gdb)tlsdump -c Output: Check: PASS Change-Id: I2f1885f75e41d105adf5eb0d05348a613447f7d3 Signed-off-by: ganjing --- tools/pynuttx/nxgdb/tlsdump.py | 159 +++++++++++++++++++++++++++++++++ tools/pynuttx/nxgdb/utils.py | 14 +++ 2 files changed, 173 insertions(+) create mode 100644 tools/pynuttx/nxgdb/tlsdump.py diff --git a/tools/pynuttx/nxgdb/tlsdump.py b/tools/pynuttx/nxgdb/tlsdump.py new file mode 100644 index 00000000000..0d2fc811bca --- /dev/null +++ b/tools/pynuttx/nxgdb/tlsdump.py @@ -0,0 +1,159 @@ +############################################################################ +# tools/pynuttx/nxgdb/tlsdump.py +# +# Licensed to the Apache Software Foundation (ASF) under one or more +# contributor license agreements. See the NOTICE file distributed with +# this work for additional information regarding copyright ownership. The +# ASF licenses this file to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance with the +# License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# +############################################################################ + +import argparse + +import gdb + +from . import utils +from .lists import NxDQueue + +CONFIG_TLS_TASK_NELEM = utils.get_field_nitems("struct task_info_s", "ta_telem") +CONFIG_TLS_NELEM = utils.get_field_nitems("struct tls_info_s", "tl_elem") + +tls_info_s = utils.lookup_type("struct tls_info_s").pointer() + + +class TlsDump(gdb.Command): + """Dump and check the integrity of tls_info and task_info""" + + def __init__(self): + if not CONFIG_TLS_NELEM: + print("TLS is not enabled in the current configuration") + return + super().__init__("tlsdump", gdb.COMMAND_USER) + + def parse_arguments(self, argv): + parser = argparse.ArgumentParser(description=self.__doc__) + parser.add_argument( + "-p", + "--pid", + type=int, + help="Dump the tls info of the thread/task represented by this pid", + default=None, + ) + parser.add_argument( + "-c", + "--check", + action="store_true", + help="Integrity check.All threads in a task must share the same task_info", + ) + + try: + args = parser.parse_args(argv) + except SystemExit: + return None + + return args + + def dump_tls(self, tcb): + """dump tls info""" + + try: + if not tcb or not utils.get_tcb_type(tcb): + return + + pid = int(tcb.pid) + type = utils.get_tcb_type(tcb) + task_info = tcb.stack_alloc_ptr.cast(tls_info_s).tl_task + print(f"PID:{pid}, {type}, task_info addr:{hex(task_info)}") + + if type == "TASK": + print("task tls elements:") + for i in range(CONFIG_TLS_TASK_NELEM): + tls = utils.get_task_tls(pid, i) + print(f"{hex(tls)}") + + print("thread tls elements:") + for i in range(CONFIG_TLS_NELEM): + tls = utils.get_thread_tls(pid, i) + print(f"{hex(tls)}") + except gdb.error: + return + + def check_corruption(self, tcb): + """integrity check""" + + try: + if not tcb or not utils.get_tcb_type(tcb): + print("No tcb found, or the tcb type is invalid") + return True + + # Get the task_info of the task, and compare it with the task_info of each thread + # If the tcb is a task, get the task_info of the task + # If the tcb is a thread, get the task_info of the task to which the thread belongs + task = ( + tcb + if utils.get_tcb_type(tcb) == "TASK" + else utils.get_tcb(tcb.group.tg_pid) + ) + if not task: + print("Can not find the task within the group") + return True + + task_info = task.stack_alloc_ptr.cast(tls_info_s).tl_task + corrupted = False + # Traverse all threads under this task through the group linked list + for tcb in NxDQueue(task.group.tg_members, "struct tcb_s", "member"): + # Get the task_info of this thread + info = tcb.stack_alloc_ptr.cast(tls_info_s).tl_task + # Only report when corrupted + if info != task_info: + pid = int(tcb.pid) + print( + f"PID:{pid} is corrupted, task_info addr:{hex(task_info)}, got {hex(info)}" + ) + corrupted = True + return corrupted + except gdb.error: + print("Error occurred during integrity check") + return True + + def invoke(self, args, from_tty): + args = self.parse_arguments(gdb.string_to_argv(args)) + if not args: + return + + # tlsdump -c + # Do integrity check + if args.check: + corrupted = any(self.check_corruption(tcb) for tcb in utils.get_tcbs()) + print(f"Check: {'FAILED' if corrupted else 'PASS'}") + return + + # tlsdump / tlsdump -p pid + pid = args.pid + tcbs = [utils.get_tcb(pid)] if pid is not None else utils.get_tcbs() + for tcb in tcbs: + if not tcb: + print(f"Pid={pid}, no task or thread found") + continue + self.dump_tls(tcb) + + def diagnose(self, *args, **kwargs): + corrupted = any(self.check_corruption(tcb) for tcb in utils.get_tcbs()) + + return { + "title": "tlsdump report", + "summary": "integrity check", + "result": "failed" if corrupted else "pass", + "command": "tlsdump", + "data": gdb.execute("tlsdump", to_string=True), + } diff --git a/tools/pynuttx/nxgdb/utils.py b/tools/pynuttx/nxgdb/utils.py index e75bea23932..83a5a79bc43 100644 --- a/tools/pynuttx/nxgdb/utils.py +++ b/tools/pynuttx/nxgdb/utils.py @@ -834,6 +834,20 @@ def get_tcb(pid) -> Tcb: return tcb +def get_tcb_type(tcb): + """get tcb type""" + if not tcb: + return None + + mask = get_symbol_value("TCB_FLAG_TTYPE_MASK") + if tcb["flags"] & mask == get_symbol_value("TCB_FLAG_TTYPE_PTHREAD"): + return "PTHREAD" + elif tcb["flags"] & mask == get_symbol_value("TCB_FLAG_TTYPE_KERNEL"): + return "KTHREAD" + else: + return "TASK" + + def get_tid(tcb): """get tid from tcb""" if not tcb: -- Gitee From 00780ffdbde8061b05fbca113bc2d5d097a11455 Mon Sep 17 00:00:00 2001 From: wangmingrong1 Date: Tue, 4 Mar 2025 17:31:55 +0800 Subject: [PATCH 120/235] gdb plugin: Support gdb parse thread info VELAPLATFO-55147 Change-Id: I0befd8908e9f09c05cf3b422afbeb02820dccead Signed-off-by: wangmingrong1 --- tools/pynuttx/nxgdb/utils.py | 54 ++++++++++++++++++++++++++++++++++++ 1 file changed, 54 insertions(+) diff --git a/tools/pynuttx/nxgdb/utils.py b/tools/pynuttx/nxgdb/utils.py index 83a5a79bc43..8d9e1aab9e5 100644 --- a/tools/pynuttx/nxgdb/utils.py +++ b/tools/pynuttx/nxgdb/utils.py @@ -1197,3 +1197,57 @@ class Addr2Line(gdb.Command): except gdb.error as e: gdb.write(f"Ignore {arg}: {e}\n") self.print_backtrace(addresses) + + +def get_gdb_thread_pid(thread: gdb.InferiorThread) -> int: + idlepid = get_symbol_value("PID0_REPLACE") + return 0 if thread.ptid[1] == idlepid else thread.ptid[1] + + +def get_gdb_thread(pid: int) -> Optional[gdb.InferiorThread]: + for thread in gdb.selected_inferior().threads(): + if get_gdb_thread_pid(thread) == pid: + return thread + return None + + +def get_thread_frames(arg: Union[gdb.InferiorThread, int]) -> Union[List[gdb.Frame]]: + thread = arg + if isinstance(arg, int): + thread = get_gdb_thread(arg) + + if not thread: + return [] + thread.switch() + + frames = [] + frame = gdb.newest_frame() + while frame and frame.is_valid(): + frames.append(frame) + frame = frame.older() + + return frames + + +def get_backtrace(arg: Union[gdb.InferiorThread, int]) -> List[int]: + backtrace = [] + + for frame in get_thread_frames(arg): + backtrace.append(frame.pc()) + + return backtrace + + +def get_frame_variables(frame: gdb.Frame) -> dict: + varibles = {} + try: + block = frame.block() + while block and block.is_valid(): + for symbol in block: + if symbol.is_valid() and symbol.is_variable: + varibles[symbol.name] = symbol.value(frame) + block = block.superblock + except RuntimeError: + pass + + return varibles -- Gitee From 433a3ddac27106e6a41baf61569261b47e009138 Mon Sep 17 00:00:00 2001 From: wangmingrong1 Date: Thu, 6 Mar 2025 15:04:30 +0800 Subject: [PATCH 121/235] gdb/utils: Support recursive import of libraries VELAPLATFO-55147 Change-Id: Ie2acbc59214729821d39387efd892cd1208b1f87 Signed-off-by: wangmingrong1 --- tools/pynuttx/nxgdb/__init__.py | 1 - tools/pynuttx/nxgdb/diagnose.py | 1 - tools/pynuttx/nxgdb/utils.py | 20 +++++++++++++------- 3 files changed, 13 insertions(+), 9 deletions(-) diff --git a/tools/pynuttx/nxgdb/__init__.py b/tools/pynuttx/nxgdb/__init__.py index 254cf268e4f..c297288e972 100644 --- a/tools/pynuttx/nxgdb/__init__.py +++ b/tools/pynuttx/nxgdb/__init__.py @@ -71,7 +71,6 @@ def register_commands(event): # Register prefix commands firstly init_gdb_commands("prefix") modules.remove("prefix") - modules.remove("__init__") # Register all other modules for m in modules: diff --git a/tools/pynuttx/nxgdb/diagnose.py b/tools/pynuttx/nxgdb/diagnose.py index 28fd334351e..2ed088c02ef 100644 --- a/tools/pynuttx/nxgdb/diagnose.py +++ b/tools/pynuttx/nxgdb/diagnose.py @@ -62,7 +62,6 @@ class DiagnoseReport(gdb.Command): modules = utils.gather_modules() modules.remove("prefix") - modules.remove("__init__") commands = utils.gather_gdbcommands(modules=modules) diff --git a/tools/pynuttx/nxgdb/utils.py b/tools/pynuttx/nxgdb/utils.py index 8d9e1aab9e5..5f14a4f10c0 100644 --- a/tools/pynuttx/nxgdb/utils.py +++ b/tools/pynuttx/nxgdb/utils.py @@ -27,11 +27,11 @@ import hashlib import importlib import json import math -import os import re import shlex import sys from enum import Enum +from pathlib import Path from typing import List, Optional, Tuple, Union import gdb @@ -960,12 +960,18 @@ def get_task_argvstr(tcb: Tcb) -> List[str]: def gather_modules(dir=None) -> List[str]: - dir = os.path.normpath(dir) if dir else os.path.dirname(__file__) - return [ - os.path.splitext(os.path.basename(f))[0] - for f in os.listdir(dir) - if f.endswith(".py") - ] + dir = Path(dir).resolve() if dir else Path(__file__).parent + modules = [] + + for f in dir.rglob("*.py"): + if f.name == "__init__.py": + continue + + relative_path = f.relative_to(dir).with_suffix("") + module_name = ".".join(relative_path.parts) + modules.append(module_name) + + return modules def gather_gdbcommands(modules=None, path=None) -> List[gdb.Command]: -- Gitee From 4c2d6edbef713afceed6fb03018cc65e38045565 Mon Sep 17 00:00:00 2001 From: wangmingrong1 Date: Fri, 7 Mar 2025 12:17:48 +0800 Subject: [PATCH 122/235] utils: Support sem_is_mutex API VELAPLATFO-55147 Change-Id: I4f98cc517284b600a4769aac92d90e2c26267712 Signed-off-by: wangmingrong1 --- tools/pynuttx/nxgdb/thread.py | 7 +++---- tools/pynuttx/nxgdb/utils.py | 4 ++++ 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/tools/pynuttx/nxgdb/thread.py b/tools/pynuttx/nxgdb/thread.py index 6bba7d90d26..ca4feff81e7 100644 --- a/tools/pynuttx/nxgdb/thread.py +++ b/tools/pynuttx/nxgdb/thread.py @@ -32,7 +32,6 @@ from . import utils from .stack import Stack UINT16_MAX = 0xFFFF -SEM_TYPE_MUTEX = 4 TSTATE_TASK_RUNNING = utils.get_symbol_value("TSTATE_TASK_RUNNING") CONFIG_SMP_NCPUS = utils.get_symbol_value("CONFIG_SMP_NCPUS") or 1 @@ -215,7 +214,7 @@ class Nxinfothreads(gdb.Command): if tcb["task_state"] == gdb.parse_and_eval("TSTATE_WAIT_SEM"): mutex = tcb["waitobj"].cast(utils.lookup_type("sem_t").pointer()) - if mutex["flags"] & SEM_TYPE_MUTEX: + if utils.sem_is_mutex(mutex["flags"]): mutex = tcb["waitobj"].cast(utils.lookup_type("mutex_t").pointer()) statename = f"Waiting,Mutex:{mutex['holder']}" @@ -446,7 +445,7 @@ class Ps(gdb.Command): waiter = ( str(int(cast2ptr(tcb["waitobj"], "mutex_t")["holder"])) if tcb["waitobj"] - and cast2ptr(tcb["waitobj"], "sem_t")["flags"] & get_macro("SEM_TYPE_MUTEX") + and utils.sem_is_mutex(cast2ptr(tcb["waitobj"], "sem_t")["flags"]) else "" ) state_and_event = eval2str(TaskState, (tcb["task_state"])) + ( @@ -589,7 +588,7 @@ class DeadLock(gdb.Command): return False sem = tcb["waitobj"].cast(utils.lookup_type("sem_t").pointer()) - if not sem["flags"] & SEM_TYPE_MUTEX: + if not utils.sem_is_mutex(sem["flags"]): return False # It's waiting on a mutex diff --git a/tools/pynuttx/nxgdb/utils.py b/tools/pynuttx/nxgdb/utils.py index 5f14a4f10c0..875f2a39fbe 100644 --- a/tools/pynuttx/nxgdb/utils.py +++ b/tools/pynuttx/nxgdb/utils.py @@ -866,6 +866,10 @@ def get_task_name(tcb): return "" +def sem_is_mutex(sem): + return sem & get_symbol_value("SEM_TYPE_MUTEX") + + def switch_inferior(inferior): state = suppress_cli_notifications(True) -- Gitee From 16aa845a9028f6d911070d574c6c7fe1d25460b0 Mon Sep 17 00:00:00 2001 From: wangmingrong1 Date: Fri, 7 Mar 2025 12:07:32 +0800 Subject: [PATCH 123/235] deadlock: Classified as a crash class VELAPLATFO-55147 Change-Id: I6e8dd703c5d6e987393ed7a9f12bf8f55e79b1a4 Signed-off-by: wangmingrong1 --- tools/pynuttx/nxgdb/nxcrash/deadlock.py | 93 +++++++++++++++++++++++++ tools/pynuttx/nxgdb/prefix.py | 7 ++ tools/pynuttx/nxgdb/thread.py | 66 ------------------ 3 files changed, 100 insertions(+), 66 deletions(-) create mode 100644 tools/pynuttx/nxgdb/nxcrash/deadlock.py diff --git a/tools/pynuttx/nxgdb/nxcrash/deadlock.py b/tools/pynuttx/nxgdb/nxcrash/deadlock.py new file mode 100644 index 00000000000..d5febe113de --- /dev/null +++ b/tools/pynuttx/nxgdb/nxcrash/deadlock.py @@ -0,0 +1,93 @@ +############################################################################ +# tools/pynuttx/nxgdb/nxcrash/deadlock.py +# +# SPDX-License-Identifier: Apache-2.0 +# +# Licensed to the Apache Software Foundation (ASF) under one or more +# contributor license agreements. See the NOTICE file distributed with +# this work for additional information regarding copyright ownership. The +# ASF licenses this file to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance with the +# License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# +############################################################################ + +from __future__ import annotations + +import gdb + +from .. import utils + + +class DeadLock(gdb.Command): + """Detect and report if threads have deadlock.""" + + def __init__(self): + super().__init__("deadlock", gdb.COMMAND_USER) + + def has_deadlock(self, pid): + """Check if the thread has a deadlock""" + tcb = utils.get_tcb(pid) + if not tcb or not tcb["waitobj"]: + return False + + sem = tcb["waitobj"].cast(utils.lookup_type("sem_t").pointer()) + if not utils.sem_is_mutex(sem["flags"]): + return False + + # It's waiting on a mutex + mutex = tcb["waitobj"].cast(utils.lookup_type("mutex_t").pointer()) + holder = mutex["holder"] + if holder in self.holders: + return True + + self.holders.append(holder) + return self.has_deadlock(holder) + + def collect(self, tcbs): + """Collect the deadlock information""" + + detected = [] + collected = [] + for tcb in tcbs: + self.holders = [] # Holders for this tcb + pid = tcb["pid"] + if pid in detected or not self.has_deadlock(tcb["pid"]): + continue + + # Deadlock detected + detected.append(pid) + detected.extend(self.holders) + collected.append((pid, self.holders)) + + return collected + + def diagnose(self, *args, **kwargs): + collected = self.collect(utils.get_tcbs()) + + return { + "title": "Deadlock Report", + "summary": f"{'No' if not collected else len(collected)} deadlocks", + "command": "crash deadlock", + "deadlocks": {int(pid): [i for i in h] for pid, h in collected}, + } + + def invoke(self, args, from_tty): + collected = self.collect(utils.get_tcbs()) + if not collected: + gdb.write("No deadlock detected.") + return + + for pid, holders in collected: + gdb.write(f'Thread {pid} "{utils.get_task_name(pid)}" has deadlocked!\n') + gdb.write(f" holders: {pid}->") + gdb.write("->".join(str(pid) for pid in holders)) + gdb.write("\n") diff --git a/tools/pynuttx/nxgdb/prefix.py b/tools/pynuttx/nxgdb/prefix.py index b232a854dd0..9949ca2e9f2 100644 --- a/tools/pynuttx/nxgdb/prefix.py +++ b/tools/pynuttx/nxgdb/prefix.py @@ -42,3 +42,10 @@ class UVDumpPrefix(gdb.Command): def __init__(self): super().__init__("uv", gdb.COMMAND_USER, prefix=True) + + +class CrashPrefix(gdb.Command): + """Crash Dump related commands prefix""" + + def __init__(self): + super().__init__("crash", gdb.COMMAND_USER, prefix=True) diff --git a/tools/pynuttx/nxgdb/thread.py b/tools/pynuttx/nxgdb/thread.py index ca4feff81e7..87a0d987b4a 100644 --- a/tools/pynuttx/nxgdb/thread.py +++ b/tools/pynuttx/nxgdb/thread.py @@ -573,69 +573,3 @@ class Ps(gdb.Command): for tcb in utils.get_tcbs(): self.parse_and_show_info(tcb) - - -class DeadLock(gdb.Command): - """Detect and report if threads have deadlock.""" - - def __init__(self): - super().__init__("deadlock", gdb.COMMAND_USER) - - def has_deadlock(self, pid): - """Check if the thread has a deadlock""" - tcb = utils.get_tcb(pid) - if not tcb or not tcb["waitobj"]: - return False - - sem = tcb["waitobj"].cast(utils.lookup_type("sem_t").pointer()) - if not utils.sem_is_mutex(sem["flags"]): - return False - - # It's waiting on a mutex - mutex = tcb["waitobj"].cast(utils.lookup_type("mutex_t").pointer()) - holder = mutex["holder"] - if holder in self.holders: - return True - - self.holders.append(holder) - return self.has_deadlock(holder) - - def collect(self, tcbs): - """Collect the deadlock information""" - - detected = [] - collected = [] - for tcb in tcbs: - self.holders = [] # Holders for this tcb - pid = tcb["pid"] - if pid in detected or not self.has_deadlock(tcb["pid"]): - continue - - # Deadlock detected - detected.append(pid) - detected.extend(self.holders) - collected.append((pid, self.holders)) - - return collected - - def diagnose(self, *args, **kwargs): - collected = self.collect(utils.get_tcbs()) - - return { - "title": "Deadlock Report", - "summary": f"{'No' if not collected else len(collected)} deadlocks", - "command": "deadlock", - "deadlocks": {int(pid): [i for i in h] for pid, h in collected}, - } - - def invoke(self, args, from_tty): - collected = self.collect(utils.get_tcbs()) - if not collected: - gdb.write("No deadlock detected.") - return - - for pid, holders in collected: - gdb.write(f'Thread {pid} "{utils.get_task_name(pid)}" has deadlocked!\n') - gdb.write(f" holders: {pid}->") - gdb.write("->".join(str(pid) for pid in holders)) - gdb.write("\n") -- Gitee From 60176184e5fa056aae9a645ba893a64a1d3be73f Mon Sep 17 00:00:00 2001 From: wangmingrong1 Date: Fri, 7 Mar 2025 18:48:38 +0800 Subject: [PATCH 124/235] gdb plugin: Support get_frame_func_name API VELAPLATFO-55147 Change-Id: I4da3099cdce6c7f3bdda2427137591da61483a54 Signed-off-by: wangmingrong1 --- tools/pynuttx/nxgdb/utils.py | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/tools/pynuttx/nxgdb/utils.py b/tools/pynuttx/nxgdb/utils.py index 875f2a39fbe..ee18fb59e93 100644 --- a/tools/pynuttx/nxgdb/utils.py +++ b/tools/pynuttx/nxgdb/utils.py @@ -1248,6 +1248,14 @@ def get_backtrace(arg: Union[gdb.InferiorThread, int]) -> List[int]: return backtrace +def get_frame_func_name(frame: gdb.Frame) -> str: + function = frame.function() + if function and function.is_valid(): + return function.name + + return "" + + def get_frame_variables(frame: gdb.Frame) -> dict: varibles = {} try: -- Gitee From c801f29b80587b8dcde9fd28fb1dcbedf91c265c Mon Sep 17 00:00:00 2001 From: wangmingrong1 Date: Fri, 7 Mar 2025 13:28:59 +0800 Subject: [PATCH 125/235] gdb-crash/thread: Support assert function found VELAPLATFO-55147 Change-Id: I1379a83c94ea02de479844c2a7fac3aa29e34d07 Signed-off-by: wangmingrong1 --- tools/pynuttx/nxgdb/nxcrash/thread.py | 67 +++++++++++++++++++++++++++ 1 file changed, 67 insertions(+) create mode 100644 tools/pynuttx/nxgdb/nxcrash/thread.py diff --git a/tools/pynuttx/nxgdb/nxcrash/thread.py b/tools/pynuttx/nxgdb/nxcrash/thread.py new file mode 100644 index 00000000000..bd268549c1b --- /dev/null +++ b/tools/pynuttx/nxgdb/nxcrash/thread.py @@ -0,0 +1,67 @@ +############################################################################ +# tools/pynuttx/nxgdb/nxcrash/thread.py +# +# SPDX-License-Identifier: Apache-2.0 +# +# Licensed to the Apache Software Foundation (ASF) under one or more +# contributor license agreements. See the NOTICE file distributed with +# this work for additional information regarding copyright ownership. The +# ASF licenses this file to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance with the +# License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# +############################################################################ + +import gdb + +from .. import utils + + +class CrashThread(gdb.Command): + """Analyse and collect the crashed threads""" + + def __init__(self): + super().__init__("crash thread", gdb.COMMAND_USER) + + def collect(self, tcbs): + """Collect threads that crashed information""" + + collected = [] + for tcb in tcbs: + pid = int(tcb["pid"]) + for frame in utils.get_thread_frames(pid): + if "_assert" in utils.get_frame_func_name(frame): + collected.append(tcb) + break + + return collected + + def invoke(self, arg: str, from_tty: bool) -> None: + collected = self.collect(utils.get_tcbs()) + + if not collected: + gdb.write("No crashed threads found") + return + + print(f"Found crashed threads\n{'PID':<4} {'Name':<10}") + for tcb in collected: + print("{:<4} {:<10}".format(tcb["pid"], utils.get_task_name(tcb))) + + def diagnose(self, *args, **kwargs): + tcbs = self.collect(utils.get_tcbs()) + return { + "title": "Threads that seem crashed", + "summary": f"{'No' if not tcbs else len(tcbs)} threads seem crashed", + "command": "crash thread", + "thread": [ + {"pid": tcb["pid"], "name": utils.get_task_name(tcb)} for tcb in tcbs + ], + } -- Gitee From 21e02ae45cc26da5cb1ee0be065e705f034834e4 Mon Sep 17 00:00:00 2001 From: ganjing Date: Mon, 10 Mar 2025 11:45:35 +0800 Subject: [PATCH 126/235] fix: check invalid tcb VELAPLATFO-55620 Change-Id: I0e0eea9e62011e5c01e24c68720811070b49ebca Signed-off-by: ganjing --- tools/pynuttx/nxgdb/utils.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/tools/pynuttx/nxgdb/utils.py b/tools/pynuttx/nxgdb/utils.py index ee18fb59e93..f29858d72f1 100644 --- a/tools/pynuttx/nxgdb/utils.py +++ b/tools/pynuttx/nxgdb/utils.py @@ -859,6 +859,9 @@ def get_tid(tcb): def get_task_name(tcb): + if not tcb: + return "" + try: name = tcb["name"].cast(gdb.lookup_type("char").pointer()) return name.string() -- Gitee From d47ef869c09463b39e88722df932fdf9f67e1891 Mon Sep 17 00:00:00 2001 From: Bowen Wang Date: Mon, 10 Mar 2025 19:56:16 +0800 Subject: [PATCH 127/235] nxgdb/rpmsg.py: continue dump even the cann't access the vring memory VELAPLATFO-55700 Avoid stop dump when can't access the share memory in the virtqueue Change-Id: Ic93fc762db9100d8d4cd573d16362bd787d82280 Signed-off-by: Bowen Wang --- tools/pynuttx/nxgdb/rpmsg.py | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/tools/pynuttx/nxgdb/rpmsg.py b/tools/pynuttx/nxgdb/rpmsg.py index ccf5f8a9fdc..02bb5d851a6 100644 --- a/tools/pynuttx/nxgdb/rpmsg.py +++ b/tools/pynuttx/nxgdb/rpmsg.py @@ -131,8 +131,11 @@ class RPMsgDump(gdb.Command): gdb.write("Rpmsg Virtqueues:\n") self.print_headers(self.VQ_HEADER, self.VQ_FORMATTER) - self.dump_virtqueue(rvdev["svq"]) - self.dump_virtqueue(rvdev["rvq"]) + try: + self.dump_virtqueue(rvdev["svq"]) + self.dump_virtqueue(rvdev["rvq"]) + except gdb.error as e: + gdb.write(f"Error when dump virtqueues: {e}\n") gdb.write("\n") -- Gitee From b984283494286276a2dcdfafbe73343e90c17b9a Mon Sep 17 00:00:00 2001 From: Bowen Wang Date: Mon, 10 Mar 2025 20:10:40 +0800 Subject: [PATCH 128/235] nxgdb/rpmsg.py: add local_cpuname and cpuname dump VELAPLATFO-55700 Dump the local_cpuname and remote cpuname, it's convenient for debug. Change-Id: I840284bc8c0226aac791143dd576e3159ba59591 Signed-off-by: Bowen Wang --- tools/pynuttx/nxgdb/rpmsg.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/tools/pynuttx/nxgdb/rpmsg.py b/tools/pynuttx/nxgdb/rpmsg.py index 02bb5d851a6..3a5db18fd80 100644 --- a/tools/pynuttx/nxgdb/rpmsg.py +++ b/tools/pynuttx/nxgdb/rpmsg.py @@ -238,7 +238,10 @@ class RPMsgDump(gdb.Command): for rpmsg in NxList(gdb.parse_and_eval("g_rpmsg"), "struct rpmsg_s", "node"): rdev = utils.Value(int(rpmsg) + utils.sizeof("struct rpmsg_s")) rdev = rdev.cast(utils.lookup_type("struct rpmsg_device").pointer()) - gdb.write(f"Rpmsg Device: rpmsg:{rpmsg} rdev:{rdev}\n") + gdb.write( + f"Rpmsg Device: rpmsg:{rpmsg} rdev:{rdev} " + f"localcpu:{rpmsg['local_cpuname']} remotecpu:{rpmsg['cpuname']}\n" + ) if not transport_only: self.dump_rdev(rdev) self.dump_rpmsg_virtio(rdev) -- Gitee From cc37218920673555c563984de9646b117ac22f02 Mon Sep 17 00:00:00 2001 From: Bowen Wang Date: Mon, 10 Mar 2025 21:11:45 +0800 Subject: [PATCH 129/235] nxgdb/rpmsg.py: optimize the rpmsg dump format VELAPLATFO-55700 1. dump the endpoint name first and move the endpoint address to the last to make the print look pretty; 2. ajust the dump label to make the content more clear; Change-Id: I3490162b873f674e983b243b9a62ca25be9b8f43 Signed-off-by: Bowen Wang --- tools/pynuttx/nxgdb/rpmsg.py | 22 +++++++++++++--------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/tools/pynuttx/nxgdb/rpmsg.py b/tools/pynuttx/nxgdb/rpmsg.py index 3a5db18fd80..6eae8a83f41 100644 --- a/tools/pynuttx/nxgdb/rpmsg.py +++ b/tools/pynuttx/nxgdb/rpmsg.py @@ -33,13 +33,13 @@ class RPMsgDump(gdb.Command): CALLBACK_HEADER = ["rpmsg_cb_s at", "ns_match", "ns_bind"] ENDPOINT_HEADER = [ - "endpoint_addr", "name", "addr", - "dest_addr", + "dest", "cb", "ns_bound_cb", "ns_unbind_cb", + "endpoint", ] VQ_HEADER = [ "vq", @@ -57,7 +57,7 @@ class RPMsgDump(gdb.Command): ] CALLBACK_FORAMTTER = "{:<20} {:<40} {:<40}" - ENDPOINT_FORMATTER = "{:<20} {:<20} {:<12} {:<12} {:<40} {:<40} {:<40}" + ENDPOINT_FORMATTER = "{:<24} {:<5} {:<11} {:<40} {:<40} {:<40} {:<20}" VQ_FORMATTER = ( "{:<12} {:<8} {:<5} {:<5} {:<7} {:<14} {:<14} {:<10} {:<12} {:<14} {:<9} {:<11}" ) @@ -122,8 +122,9 @@ class RPMsgDump(gdb.Command): rvdev = rdev.cast(utils.lookup_type("struct rpmsg_virtio_device").pointer()) + gdb.write("Rpmsg VirtIO Transport:\n") gdb.write( - f"Rpmsg Virtio Trasport: rvdev:{rvdev} h2r_buf_size:{rvdev['config']['h2r_buf_size']}" + f"rvdev:{rvdev} h2r_buf_size:{rvdev['config']['h2r_buf_size']}" f"r2h_buf_size:{rvdev['config']['r2h_buf_size']}\n" ) for vbuff in NxList(rvdev["reclaimer"], "struct vbuff_reclaimer_t", "node"): @@ -191,20 +192,21 @@ class RPMsgDump(gdb.Command): gdb.write(formatter.format(*["-" * len(header) for header in headers]) + "\n") def dump_rdev_epts(self, endpoints_head): - gdb.write(f"dump_rdev_epts:{endpoints_head}\n") + gdb.write("Rpmsg Device Endpoints:\n") + gdb.write(f"endpoints list:{endpoints_head}\n") self.print_headers(self.ENDPOINT_HEADER, self.ENDPOINT_FORMATTER) output = [] for endpoint in NxList(endpoints_head, "struct rpmsg_endpoint", "node"): output.append( self.ENDPOINT_FORMATTER.format( - f"{endpoint}", f"{endpoint['name'].string()}", f"{endpoint['addr']}", f"{endpoint['dest_addr']}", f"{endpoint['cb']}", f"{endpoint['ns_bound_cb']}", f"{endpoint['ns_unbind_cb']}", + f"{endpoint}", ) ) @@ -214,10 +216,12 @@ class RPMsgDump(gdb.Command): bitmap_values = [hex(bit) for bit in utils.ArrayIterator(rdev["bitmap"])] gdb.write( - f"bitmap:{' '.join(bitmap_values):<20} bitmaplast: {rdev['bitmap']}\n" + f"bitmap: {' '.join(bitmap_values):<20} bitnext: {hex(rdev['bitnext'])}\n" ) def dump_rdev(self, rdev): + gdb.write("Rpmsg Device:\n") + gdb.write(f"rdev:{rdev}\n") self.dump_rdev_bitmap(rdev) self.dump_rdev_epts(rdev["endpoints"]) @@ -239,8 +243,8 @@ class RPMsgDump(gdb.Command): rdev = utils.Value(int(rpmsg) + utils.sizeof("struct rpmsg_s")) rdev = rdev.cast(utils.lookup_type("struct rpmsg_device").pointer()) gdb.write( - f"Rpmsg Device: rpmsg:{rpmsg} rdev:{rdev} " - f"localcpu:{rpmsg['local_cpuname']} remotecpu:{rpmsg['cpuname']}\n" + f"Rpmsg:\n" + f"rpmsg:{rpmsg} localcpu:{rpmsg['local_cpuname']} remotecpu:{rpmsg['cpuname']}\n" ) if not transport_only: self.dump_rdev(rdev) -- Gitee From c23d54b2a9e7fd6f05368d8b802233ac6d18eda4 Mon Sep 17 00:00:00 2001 From: wangmingrong1 Date: Fri, 7 Mar 2025 16:20:44 +0800 Subject: [PATCH 130/235] utils: Support task is running or not VELAPLATFO-55147 Delete unused definitions Change-Id: Iee77bbc8963e4e5dc366023bf032525c74ed8a3e Signed-off-by: wangmingrong1 --- tools/pynuttx/nxgdb/nxcrash/deadlock.py | 2 +- tools/pynuttx/nxgdb/nxcrash/thread.py | 2 +- tools/pynuttx/nxgdb/thread.py | 12 ++++-------- tools/pynuttx/nxgdb/utils.py | 6 ++++++ 4 files changed, 12 insertions(+), 10 deletions(-) diff --git a/tools/pynuttx/nxgdb/nxcrash/deadlock.py b/tools/pynuttx/nxgdb/nxcrash/deadlock.py index d5febe113de..99b6e4c57d3 100644 --- a/tools/pynuttx/nxgdb/nxcrash/deadlock.py +++ b/tools/pynuttx/nxgdb/nxcrash/deadlock.py @@ -83,7 +83,7 @@ class DeadLock(gdb.Command): def invoke(self, args, from_tty): collected = self.collect(utils.get_tcbs()) if not collected: - gdb.write("No deadlock detected.") + gdb.write("No deadlock detected.\n") return for pid, holders in collected: diff --git a/tools/pynuttx/nxgdb/nxcrash/thread.py b/tools/pynuttx/nxgdb/nxcrash/thread.py index bd268549c1b..13fa5859296 100644 --- a/tools/pynuttx/nxgdb/nxcrash/thread.py +++ b/tools/pynuttx/nxgdb/nxcrash/thread.py @@ -48,7 +48,7 @@ class CrashThread(gdb.Command): collected = self.collect(utils.get_tcbs()) if not collected: - gdb.write("No crashed threads found") + gdb.write("No crashed threads found.\n") return print(f"Found crashed threads\n{'PID':<4} {'Name':<10}") diff --git a/tools/pynuttx/nxgdb/thread.py b/tools/pynuttx/nxgdb/thread.py index 87a0d987b4a..d2e7dc5b0ec 100644 --- a/tools/pynuttx/nxgdb/thread.py +++ b/tools/pynuttx/nxgdb/thread.py @@ -31,8 +31,6 @@ from nxreg.register import Registers, g_reg_table from . import utils from .stack import Stack -UINT16_MAX = 0xFFFF -TSTATE_TASK_RUNNING = utils.get_symbol_value("TSTATE_TASK_RUNNING") CONFIG_SMP_NCPUS = utils.get_symbol_value("CONFIG_SMP_NCPUS") or 1 @@ -80,7 +78,7 @@ class NxRegisters: gdb.write(f"Thread {pid} not found\n") return - if tcb["task_state"] == TSTATE_TASK_RUNNING: + if utils.task_is_running(tcb): # If the thread is running, then register is not in context but saved temporarily self.restore() return @@ -200,7 +198,7 @@ class Nxinfothreads(gdb.Command): pid = tcb["group"]["tg_pid"] tid = tcb["pid"] - if tcb["task_state"] == gdb.parse_and_eval("TSTATE_TASK_RUNNING"): + if utils.task_is_running(tcb): index = f"*{i}" pc = utils.get_pc() else: @@ -332,9 +330,7 @@ class Nxthread(gdb.Command): and int(arg[0]) < npidhash and pidhash[int(arg[0])] != 0 ): - if pidhash[int(arg[0])]["task_state"] == gdb.parse_and_eval( - "TSTATE_TASK_RUNNING" - ): + if utils.task_is_running(pidhash[int(arg[0])]): g_registers.restore() else: gdb.execute("setregs g_pidhash[%s]->xcp.regs" % arg[0]) @@ -475,7 +471,7 @@ class Ps(gdb.Command): int(tcb["stack_base_ptr"]), int(tcb["stack_alloc_ptr"]), int(tcb["adj_stack_size"]), - utils.get_sp(tcb if tcb["task_state"] != TSTATE_TASK_RUNNING else None), + utils.get_sp(tcb if not utils.task_is_running(tcb) else None), 4, ) diff --git a/tools/pynuttx/nxgdb/utils.py b/tools/pynuttx/nxgdb/utils.py index f29858d72f1..ce61112142a 100644 --- a/tools/pynuttx/nxgdb/utils.py +++ b/tools/pynuttx/nxgdb/utils.py @@ -766,6 +766,7 @@ def in_interrupt_context(cpuid=0): return not g_current_regs or not g_current_regs[cpuid] +# task def get_register_byname(regname, tcb=None): frame = gdb.selected_frame() @@ -869,6 +870,11 @@ def get_task_name(tcb): return "" +def task_is_running(tcb): + return tcb["task_state"] == get_symbol_value("TSTATE_TASK_RUNNING") + + +# sem def sem_is_mutex(sem): return sem & get_symbol_value("SEM_TYPE_MUTEX") -- Gitee From 88e70ef0cf0da30d1d66bbffbbd06f7ee746f651 Mon Sep 17 00:00:00 2001 From: wangmingrong1 Date: Fri, 7 Mar 2025 16:37:11 +0800 Subject: [PATCH 131/235] gdb/crash: Support stack overflow detect VELAPLATFO-55147 Change-Id: I0ab3e70576b95bbcaf15cc06a9d6a5a71baf1c21 Signed-off-by: wangmingrong1 --- tools/pynuttx/nxgdb/nxcrash/deadlock.py | 1 + tools/pynuttx/nxgdb/nxcrash/stackoverflow.py | 79 ++++++++++++++++++++ tools/pynuttx/nxgdb/nxcrash/thread.py | 1 + 3 files changed, 81 insertions(+) create mode 100644 tools/pynuttx/nxgdb/nxcrash/stackoverflow.py diff --git a/tools/pynuttx/nxgdb/nxcrash/deadlock.py b/tools/pynuttx/nxgdb/nxcrash/deadlock.py index 99b6e4c57d3..ae5463853ea 100644 --- a/tools/pynuttx/nxgdb/nxcrash/deadlock.py +++ b/tools/pynuttx/nxgdb/nxcrash/deadlock.py @@ -76,6 +76,7 @@ class DeadLock(gdb.Command): return { "title": "Deadlock Report", "summary": f"{'No' if not collected else len(collected)} deadlocks", + "result": "fail" if collected else "pass", "command": "crash deadlock", "deadlocks": {int(pid): [i for i in h] for pid, h in collected}, } diff --git a/tools/pynuttx/nxgdb/nxcrash/stackoverflow.py b/tools/pynuttx/nxgdb/nxcrash/stackoverflow.py new file mode 100644 index 00000000000..1b9c446ea99 --- /dev/null +++ b/tools/pynuttx/nxgdb/nxcrash/stackoverflow.py @@ -0,0 +1,79 @@ +############################################################################ +# tools/pynuttx/nxgdb/nxcrash/stackoverflow.py +# +# SPDX-License-Identifier: Apache-2.0 +# +# Licensed to the Apache Software Foundation (ASF) under one or more +# contributor license agreements. See the NOTICE file distributed with +# this work for additional information regarding copyright ownership. The +# ASF licenses this file to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance with the +# License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# +############################################################################ + +import gdb + +from .. import utils +from ..stack import Stack + +STACK_FILL_THRESHOLD = 0.9 + + +class CrashStackOverflow(gdb.Command): + """Analyse and collect the stack overflow threads""" + + def __init__(self): + super().__init__("crash stackoverflow", gdb.COMMAND_USER) + + def collect(self, tcbs): + """Collect the stack overflow information""" + + collected = [] + for tcb in tcbs: + st = Stack( + utils.get_task_name(tcb), + hex(tcb["entry"]["pthread"]), # should use main? + int(tcb["stack_base_ptr"]), + int(tcb["stack_alloc_ptr"]), + int(tcb["adj_stack_size"]), + utils.get_sp(tcb), + 4, + ) + + filled = st.max_usage() / st._stack_size + if filled > STACK_FILL_THRESHOLD: + collected.append((tcb, filled)) + + return collected + + def invoke(self, arg: str, from_tty: bool) -> None: + collected = self.collect(utils.get_tcbs()) + if not collected: + gdb.write("No stack overflow found\n") + return + + print(f"Found stack overflow threads\n{'PID':<4} {'name':<10} {'FILLED'}") + for tcb, filled in collected: + print(f"{tcb['pid']:<4} {utils.get_task_name(tcb):<10} {filled:.2%}") + + def diagnose(self, *args, **kwargs): + collected = self.collect(utils.get_tcbs()) + return { + "title": "Stack OverFlow Report", + "summary": f"{'No' if not collected else len(collected)} threads{'s' if len(collected) != 1 else ''} found", + "result": "fail" if collected else "pass", + "command": "crash stackoverflow", + "thread": [ + {"pid": tcb["pid"], "name": utils.get_task_name(tcb), "filled": filled} + for tcb, filled in collected + ], + } diff --git a/tools/pynuttx/nxgdb/nxcrash/thread.py b/tools/pynuttx/nxgdb/nxcrash/thread.py index 13fa5859296..490493ba771 100644 --- a/tools/pynuttx/nxgdb/nxcrash/thread.py +++ b/tools/pynuttx/nxgdb/nxcrash/thread.py @@ -60,6 +60,7 @@ class CrashThread(gdb.Command): return { "title": "Threads that seem crashed", "summary": f"{'No' if not tcbs else len(tcbs)} threads seem crashed", + "result": "fail" if tcbs else "pass", "command": "crash thread", "thread": [ {"pid": tcb["pid"], "name": utils.get_task_name(tcb)} for tcb in tcbs -- Gitee From cf9dadb15ff51478a85863958fd31d092478c412 Mon Sep 17 00:00:00 2001 From: wangmingrong1 Date: Fri, 7 Mar 2025 16:45:41 +0800 Subject: [PATCH 132/235] gdb/utils: Support get_smp_num API VELAPLATFO-53966 Change-Id: I8bc4a4ce007512cf45b506edca89e2046824ab50 Signed-off-by: wangmingrong1 --- tools/pynuttx/nxgdb/thread.py | 6 ++---- tools/pynuttx/nxgdb/utils.py | 7 +++++++ 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/tools/pynuttx/nxgdb/thread.py b/tools/pynuttx/nxgdb/thread.py index d2e7dc5b0ec..0ff7d0112f2 100644 --- a/tools/pynuttx/nxgdb/thread.py +++ b/tools/pynuttx/nxgdb/thread.py @@ -31,13 +31,11 @@ from nxreg.register import Registers, g_reg_table from . import utils from .stack import Stack -CONFIG_SMP_NCPUS = utils.get_symbol_value("CONFIG_SMP_NCPUS") or 1 - def is_thread_command_supported(): # Check if the native thread command is available by compare the number of threads. # It should have at least CONFIG_SMP_NCPUS of idle threads. - return len(gdb.selected_inferior().threads()) > CONFIG_SMP_NCPUS + return len(gdb.selected_inferior().threads()) > utils.get_ncpus() class NxRegisters: @@ -493,7 +491,7 @@ class Ps(gdb.Command): ptcb = cast2ptr(tcb, "struct pthread_tcb_s") arg = ptcb["arg"] cmd = " ".join((name, hex(entry), hex(arg))) - elif tcb["pid"] < get_macro("CONFIG_SMP_NCPUS"): + elif tcb["pid"] < utils.get_ncpus(): # This must be the Idle Tasks, hence we just get its name cmd = name else: diff --git a/tools/pynuttx/nxgdb/utils.py b/tools/pynuttx/nxgdb/utils.py index ce61112142a..49328299a32 100644 --- a/tools/pynuttx/nxgdb/utils.py +++ b/tools/pynuttx/nxgdb/utils.py @@ -752,6 +752,13 @@ def is_target_smp(): return False +CONFIG_SMP_NCPUS = nitems(parse_and_eval("g_running_tasks")) + + +def get_ncpus(): + return CONFIG_SMP_NCPUS + + # FIXME: support RISC-V/X86/ARM64 etc. def in_interrupt_context(cpuid=0): frame = gdb.selected_frame() -- Gitee From 9a917c55713f7b2fc189c30d7987c74fb1e4194d Mon Sep 17 00:00:00 2001 From: wangmingrong1 Date: Fri, 7 Mar 2025 18:09:33 +0800 Subject: [PATCH 133/235] gdb plugin: judge task_is_running in get_sp or get_pc API VELAPLATFO-55147 Change-Id: I99d7bb5212159c92bde5d4240523c4b062366ee7 Signed-off-by: wangmingrong1 --- tools/pynuttx/nxgdb/stack.py | 5 +---- tools/pynuttx/nxgdb/thread.py | 12 +++------- tools/pynuttx/nxgdb/utils.py | 41 ++++++++++++++++------------------- 3 files changed, 23 insertions(+), 35 deletions(-) diff --git a/tools/pynuttx/nxgdb/stack.py b/tools/pynuttx/nxgdb/stack.py index 77b49139e55..04a6d4fe36b 100644 --- a/tools/pynuttx/nxgdb/stack.py +++ b/tools/pynuttx/nxgdb/stack.py @@ -146,10 +146,7 @@ def fetch_stacks(): for tcb in utils.get_tcbs(): # We have no way to detect if we are in an interrupt context for now. # Originally we use `and not utils.in_interrupt_context()` - if tcb["task_state"] == gdb.parse_and_eval("TSTATE_TASK_RUNNING"): - sp = utils.get_sp() - else: - sp = utils.get_sp(tcb=tcb) + sp = utils.get_sp(tcb) try: stacks[int(tcb["pid"])] = Stack( diff --git a/tools/pynuttx/nxgdb/thread.py b/tools/pynuttx/nxgdb/thread.py index 0ff7d0112f2..090eddf015f 100644 --- a/tools/pynuttx/nxgdb/thread.py +++ b/tools/pynuttx/nxgdb/thread.py @@ -195,15 +195,9 @@ class Nxinfothreads(gdb.Command): pid = tcb["group"]["tg_pid"] tid = tcb["pid"] - - if utils.task_is_running(tcb): - index = f"*{i}" - pc = utils.get_pc() - else: - index = f" {i}" - pc = utils.get_pc(tcb=tcb) - + pc = utils.get_pc(tcb) thread = f"Thread {hex(tcb)}" + index = f"*{i}" if utils.task_is_running(tcb) else f" {i}" statename = statenames[tcb["task_state"]].string() statename = f'\x1b{"[32;1m" if statename == "Running" else "[33;1m"}{statename}\x1b[m' @@ -469,7 +463,7 @@ class Ps(gdb.Command): int(tcb["stack_base_ptr"]), int(tcb["stack_alloc_ptr"]), int(tcb["adj_stack_size"]), - utils.get_sp(tcb if not utils.task_is_running(tcb) else None), + utils.get_sp(tcb), 4, ) diff --git a/tools/pynuttx/nxgdb/utils.py b/tools/pynuttx/nxgdb/utils.py index 49328299a32..58450cbc633 100644 --- a/tools/pynuttx/nxgdb/utils.py +++ b/tools/pynuttx/nxgdb/utils.py @@ -774,12 +774,12 @@ def in_interrupt_context(cpuid=0): # task -def get_register_byname(regname, tcb=None): +def get_register_byname(regname, tcb): frame = gdb.selected_frame() # If no tcb is given then we can directly use the register from # the cached frame by GDB - if not tcb: + if task_is_running(tcb): return int(frame.read_register(regname)) # Ok, let's take it from the context in the given tcb @@ -796,29 +796,26 @@ def get_register_byname(regname, tcb=None): return int(value.dereference()) -def get_sp(tcb=None): - regname = "sp" - if tcb is not None: - # NuttX doesn't support unified register name for stack pointer - arch = gdb.selected_inferior().architecture().name() - regname = { - "i386": "esp", - "i386:x86": "esp", - "i386:x86-64": "rsp", - }.get(arch, "sp") +def get_sp(tcb): + # NuttX doesn't support unified register name for stack pointer + arch = gdb.selected_inferior().architecture().name() + regname = { + "i386": "esp", + "i386:x86": "esp", + "i386:x86-64": "rsp", + }.get(arch, "sp") + return get_register_byname(regname, tcb) -def get_pc(tcb=None): - regname = "pc" - if tcb is not None: - # NuttX doesn't support unified register name for PC - arch = gdb.selected_inferior().architecture().name() - regname = { - "i386": "eip", - "i386:x86": "eip", - "i386:x86-64": "rip", - }.get(arch, "pc") +def get_pc(tcb): + # NuttX doesn't support unified register name for PC + arch = gdb.selected_inferior().architecture().name() + regname = { + "i386": "eip", + "i386:x86": "eip", + "i386:x86-64": "rip", + }.get(arch, "pc") return get_register_byname(regname, tcb) -- Gitee From 567760f22866082b4ea7ccdf9dc319be647ed825 Mon Sep 17 00:00:00 2001 From: wangmingrong1 Date: Wed, 12 Mar 2025 17:22:00 +0800 Subject: [PATCH 134/235] gdb plugin: Catch json.load errors and re-execute VELAPLATFO-53966 Change-Id: Ic1e573ace6bb44dc9f9a0fe40738585c41a29b51 Signed-off-by: wangmingrong1 --- tools/pynuttx/nxelf/macros.py | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/tools/pynuttx/nxelf/macros.py b/tools/pynuttx/nxelf/macros.py index ce207a60e08..1726b6430df 100644 --- a/tools/pynuttx/nxelf/macros.py +++ b/tools/pynuttx/nxelf/macros.py @@ -163,7 +163,12 @@ def fetch_macro_info(file): print(f"Cache macro info to {cache}") else: with open(cache, "r") as f2: - macros = json.load(f2) + try: + macros = json.load(f2) + except json.decoder.JSONDecodeError: + print(f"Warning: Failed to load {cache}, reprocessing...") + os.remove(cache) + return fetch_macro_info(file) return macros -- Gitee From 7b6b46ae51e20e21acdd5f2b5133f6d1732dc399 Mon Sep 17 00:00:00 2001 From: xuxingliang Date: Fri, 14 Mar 2025 23:02:04 +0800 Subject: [PATCH 135/235] nxgdb: fix CI break VELAPLATFO-56229 Should check if tcb is None or not. Introduced by https://gerrit.pt.mioffice.cn/c/vela/nuttx/+/5161759 Change-Id: Ibf81426fb13ce8d6474dd3e94a32acdb9b088054 Signed-off-by: xuxingliang --- tools/pynuttx/nxgdb/utils.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/tools/pynuttx/nxgdb/utils.py b/tools/pynuttx/nxgdb/utils.py index 58450cbc633..7a98d57bee6 100644 --- a/tools/pynuttx/nxgdb/utils.py +++ b/tools/pynuttx/nxgdb/utils.py @@ -774,12 +774,12 @@ def in_interrupt_context(cpuid=0): # task -def get_register_byname(regname, tcb): +def get_register_byname(regname, tcb=None): frame = gdb.selected_frame() # If no tcb is given then we can directly use the register from # the cached frame by GDB - if task_is_running(tcb): + if not tcb or task_is_running(tcb): return int(frame.read_register(regname)) # Ok, let's take it from the context in the given tcb @@ -796,7 +796,7 @@ def get_register_byname(regname, tcb): return int(value.dereference()) -def get_sp(tcb): +def get_sp(tcb=None): # NuttX doesn't support unified register name for stack pointer arch = gdb.selected_inferior().architecture().name() regname = { @@ -808,7 +808,7 @@ def get_sp(tcb): return get_register_byname(regname, tcb) -def get_pc(tcb): +def get_pc(tcb=None): # NuttX doesn't support unified register name for PC arch = gdb.selected_inferior().architecture().name() regname = { -- Gitee From 78506b5192d531a3a922b6665ffac7f21c384efb Mon Sep 17 00:00:00 2001 From: wangmingrong1 Date: Fri, 14 Mar 2025 21:00:06 +0800 Subject: [PATCH 136/235] gdb plugin: fix ps command when thread wait MQEmpty@Mutex suspend VELAPLATFO-53966 state_and_event: ['Waiting', 'MQEmpty@Mutex', 'Holder: 0'] Change-Id: I772367c255e29c17b77057e73d589a825532378a Signed-off-by: wangmingrong1 --- tools/pynuttx/nxgdb/thread.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/pynuttx/nxgdb/thread.py b/tools/pynuttx/nxgdb/thread.py index 090eddf015f..27a68438a20 100644 --- a/tools/pynuttx/nxgdb/thread.py +++ b/tools/pynuttx/nxgdb/thread.py @@ -437,7 +437,7 @@ class Ps(gdb.Command): else "" ) state_and_event = eval2str(TaskState, (tcb["task_state"])) + ( - "@Mutex_Holder: " + waiter if waiter else "" + "@MutexHolder: " + waiter if waiter else "" ) state_and_event = state_and_event.split("_") -- Gitee From 6a9e297f43f89bed8ac3e075cdf7de2899624495 Mon Sep 17 00:00:00 2001 From: wangmingrong1 Date: Fri, 14 Mar 2025 16:11:36 +0800 Subject: [PATCH 137/235] gdb plugin: Support task_is_idle API VELAPLATFO-53966 Change-Id: Id16b816fb9bd20e80f5b45008671378ca111e662 Signed-off-by: wangmingrong1 --- tools/pynuttx/nxgdb/utils.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/tools/pynuttx/nxgdb/utils.py b/tools/pynuttx/nxgdb/utils.py index 7a98d57bee6..c106b63f9dc 100644 --- a/tools/pynuttx/nxgdb/utils.py +++ b/tools/pynuttx/nxgdb/utils.py @@ -878,6 +878,10 @@ def task_is_running(tcb): return tcb["task_state"] == get_symbol_value("TSTATE_TASK_RUNNING") +def task_is_idle(tcb): + return tcb["pid"] < CONFIG_SMP_NCPUS + + # sem def sem_is_mutex(sem): return sem & get_symbol_value("SEM_TYPE_MUTEX") -- Gitee From 101ceeb98a2863c97cb5bb65eb41592bf361149e Mon Sep 17 00:00:00 2001 From: wangmingrong1 Date: Fri, 14 Mar 2025 16:12:10 +0800 Subject: [PATCH 138/235] gdb/crash: Support thread busyloop detect VELAPLATFO-53966 Change-Id: I7bf54bce9db96a5692f18d9d046685936df12ce1 Signed-off-by: wangmingrong1 --- tools/pynuttx/nxgdb/nxcrash/busyloop.py | 77 +++++++++++++++++++++++++ 1 file changed, 77 insertions(+) create mode 100644 tools/pynuttx/nxgdb/nxcrash/busyloop.py diff --git a/tools/pynuttx/nxgdb/nxcrash/busyloop.py b/tools/pynuttx/nxgdb/nxcrash/busyloop.py new file mode 100644 index 00000000000..bf4ccd6feaf --- /dev/null +++ b/tools/pynuttx/nxgdb/nxcrash/busyloop.py @@ -0,0 +1,77 @@ +############################################################################ +# tools/pynuttx/nxgdb/nxcrash/busyloop.py +# +# SPDX-License-Identifier: Apache-2.0 +# +# Licensed to the Apache Software Foundation (ASF) under one or more +# contributor license agreements. See the NOTICE file distributed with +# this work for additional information regarding copyright ownership. The +# ASF licenses this file to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance with the +# License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# +############################################################################ + +import gdb + +from .. import utils + +BUSYLOOP_THRESHOLD = 0.9 / utils.get_ncpus() + + +class CrashBusyloop(gdb.Command): + """Analyse and collect the busyloop threads""" + + def __init__(self): + if not utils.get_symbol_value("CONFIG_SCHED_CPULOAD_NONE"): + super().__init__("crash busyloop", gdb.COMMAND_USER) + + def collect(self, tcbs): + """Get busyloop thread""" + collected = [] + cpuload_total = int(utils.parse_and_eval("g_cpuload_total")) + + for tcb in tcbs: + cpuload = int(tcb["ticks"]) / cpuload_total + if cpuload > BUSYLOOP_THRESHOLD and not utils.task_is_idle(tcb): + collected.append((tcb, cpuload)) + + return collected + + def invoke(self, arg: str, from_tty: bool) -> None: + collected = self.collect(utils.get_tcbs()) + if not collected: + gdb.write("No busyloop threads found.\n") + return + + print(f"Found busyloop thread\n{'PID':<4} {'Name':<10} Load") + for tcb, cpuload in collected: + print( + "{:<4} {:<10} {}".format(tcb["pid"], utils.get_task_name(tcb), cpuload) + ) + + def diagnose(self, *args, **kwargs): + collected = self.collect(utils.get_tcbs()) + + return { + "title": "Busyloop Report", + "summary": f"{'No' if not collected else len(collected)} threads occur busyloop", + "result": "fail" if collected else "pass", + "command": "crash busyloop", + "thread": [ + { + "pid": tcb["pid"], + "name": utils.get_task_name(tcb), + "cpuload": cpuload, + } + for tcb, cpuload in collected + ], + } -- Gitee From 45d4648a4d4d98b170d0176d7efbbe4fad402522 Mon Sep 17 00:00:00 2001 From: guohao15 Date: Tue, 18 Feb 2025 09:04:18 +0000 Subject: [PATCH 139/235] nxgdb/fs: abstract public function get_fstype for reuse VELAPLATFO-53879 Change-Id: I5c491bd2364e80298f4e8147f0345bc93359517f Signed-off-by: guohao15 (cherry picked from commit 4637c363227924d50bc16f74a3975a035a9b7edd) --- tools/pynuttx/nxgdb/fs.py | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/tools/pynuttx/nxgdb/fs.py b/tools/pynuttx/nxgdb/fs.py index c0d77ac1109..aa3b0fd2b25 100644 --- a/tools/pynuttx/nxgdb/fs.py +++ b/tools/pynuttx/nxgdb/fs.py @@ -110,6 +110,19 @@ class Inode(utils.Value, p.Inode): return inode_gettype(self) +def get_fstype(node: p.Inode): + try: + if not node: + return "" + + statfs = node.u.i_mops.statfs + funcname = gdb.block_for_pc(int(statfs)).function.print_name + return funcname.split("_")[0] + + except gdb.MemoryError: + return "" + + def get_inode_name(inode: p.Inode): try: if not inode: @@ -337,9 +350,7 @@ class Mount(gdb.Command): lambda x: inode_gettype(x[0]) == InodeType.MOUNTPT, foreach_inode() ) for node, path in nodes: - statfs = node.u.i_mops.statfs - funcname = gdb.block_for_pc(int(statfs)).function.print_name - fstype = funcname.split("_")[0] + fstype = get_fstype(node) gdb.write(" %s type %s\n" % (path, fstype)) self.mount_count += 1 -- Gitee From b6890358722948f993b087004703de593eab1f4b Mon Sep 17 00:00:00 2001 From: guohao15 Date: Mon, 17 Feb 2025 08:32:07 +0000 Subject: [PATCH 140/235] nxgdb/fs add command "info romfs" MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit VELAPLATFO-53879 which can show detail information of romfs cached in memory E.g. (gdb) info romfs -P /system Romfs /system mount point information: 0x40861190 HW sector size: 512 HW sector number: 89856 Volume size: 46006208 XIP_addr: 0x0 Buffer_addr: 0x4085ec88 ├── / offset:32 next:1 size:0 child_count:1 │ ├── font/ offset:128 next:9 size:0 child_count:7 │ │ └── MI_Lan_Pro_Medium.ttf offset:5172176 next:13911490 size:8739260 child_count:0 │ │ └── MiSansW_Demibold.ttf offset:2594656 next:5172178 size:2577464 child_count:0 │ │ └── MiSansW_Normal.ttf offset:43396912 next:2 size:2609248 child_count:0 │ │ └── MiSansW_Regular.ttf offset:128 next:2594658 size:2594476 child_count:0 │ │ ├── plus/ offset:25698912 next:33643465 size:0 child_count:1 │ │ │ ├── font/ offset:25698944 next:33643401 size:0 child_count:1 │ │ │ │ └── MiSansW_Normal.ttf offset:25699008 next:2 size:7944332 child_count:0 │ │ └── simhei.ttf offset:33643488 next:43396922 size:9753388 child_count:0 │ │ └── simkai.ttf offset:13911520 next:25698882 size:11787328 child_count:0 Change-Id: I1e6119792b81b6dfdd6f71530dd673a7bfe97143 Signed-off-by: guohao15 (cherry picked from commit 8f5479d21bd3eb8b2411da0a30178a8f0aef071f) --- tools/pynuttx/nxgdb/fs.py | 94 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 94 insertions(+) diff --git a/tools/pynuttx/nxgdb/fs.py b/tools/pynuttx/nxgdb/fs.py index aa3b0fd2b25..91c6eb8b67e 100644 --- a/tools/pynuttx/nxgdb/fs.py +++ b/tools/pynuttx/nxgdb/fs.py @@ -514,3 +514,97 @@ class InfoShmfs(gdb.Command): self.total_size += length / 1024 self.block_count += 1 + + +class InfoRomfs(gdb.Command): + """Show romfs cache information""" + + def __init__(self): + if utils.get_symbol_value("CONFIG_FS_ROMFS_CACHE_NODE"): + super().__init__("info romfs", gdb.COMMAND_USER) + + def parse_arguments(self, argv): + parser = argparse.ArgumentParser(description=self.__doc__) + parser.add_argument( + "-P", + "--path", + type=str, + default=None, + help="set the romfs path to be dumped", + ) + + try: + args = parser.parse_args(argv) + except SystemExit: + return None + + return args + + def dump_romfs_mpt(self, mpt): + sector_size = mpt.rm_hwsectorsize + sector_num = mpt.rm_hwnsectors + volume_size = mpt.rm_volsize + xip_base = mpt.rm_xipbase + buffer_base = mpt.rm_buffer + gdb.write( + f" HW sector size: {sector_size} HW sector number: {sector_num}\n" + f" Volume size: {volume_size} XIP_addr: {hex(xip_base)}" + f" Buffer_addr: {hex(buffer_base)}\n" + ) + + def dump_romfs_files(self, node, level=1, prefix="", maxlevel=4096): + if level > maxlevel: + return + + if node.rn_count > 0: + initial_indent = prefix + "├── " + newprefix = prefix + "│ " + dirfix = "/" + else: + initial_indent = prefix + "└── " + newprefix = prefix + " " + dirfix = "" + + name = node.rn_name.string(length=node.rn_namesize) + gdb.write( + f"{initial_indent}{name}{dirfix} offset:{node.rn_offset} next:{node.rn_next}" + f" size:{node.rn_size} child_count:{node.rn_count}\n" + ) + + for child in utils.ArrayIterator(node.rn_child, node.rn_count): + self.dump_romfs_files(child, level + 1, newprefix, maxlevel) + + def dump_romfs_cache(self, node: Inode, path): + mpt = node.i_private.cast(utils.lookup_type("struct romfs_mountpt_s").pointer()) + root = mpt.rm_root.cast(utils.lookup_type("struct romfs_nodeinfo_s").pointer()) + gdb.write(f"Romfs {path} mount point information: {hex(mpt)}\n") + self.dump_romfs_mpt(mpt) + self.dump_romfs_files(root) + + def diagnose(self, *args, **kwargs): + output = gdb.execute("info romfs", to_string=True) + + return { + "title": "Romfs cache information", + "summary": "Romfs nodeinfo dump", + "command": "info romfs", + "result": "info", + "message": output or "No romfs information", + } + + def invoke(self, args, from_tty): + args = self.parse_arguments(gdb.string_to_argv(args)) + + def romfs_filter(item): + inode, path = item + if inode_gettype(inode) != InodeType.MOUNTPT: + return False + if args and args.path and path != args.path: + return False + + fstype = get_fstype(inode) + return fstype == "romfs" + + nodes = filter(romfs_filter, foreach_inode()) + for node, path in nodes: + self.dump_romfs_cache(node, path) -- Gitee From 6b53794e10d30438ef6174df8d5d530e251565d8 Mon Sep 17 00:00:00 2001 From: guohao15 Date: Tue, 18 Feb 2025 06:32:55 +0000 Subject: [PATCH 141/235] nxgdb/fs add command "info yaffs" MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit VELAPLATFO-53979 eg: (gdb) info yaffs Yaffs /yaffs mount point information: 0x408e7680 Block size:2048 Erase size:131072 Erase count:64 Dump yaffs_dev: 0x403f24d0 $110 = {param = {name = 0x4087fba0 "filemtd", inband_tags = 1, total_bytes_per_chunk = 2048, chunks_per_block = 64, spare_bytes_per_chunk = 0, start_block = 0, end_block = 63, n_reserved_blocks = 5, n_caches = 20, cache_bypass_aligned = 0, use_nand_ecc = 1, tags_9bytes = 0, no_tags_ecc = 0, is_yaffs2 = 1, empty_lost_n_found = 0, refresh_period = 1000, skip_checkpt_rd = 0 '\000', skip_checkpt_wr = 0 '\000', enable_xattr = 0, max_objects = 0, hide_lost_n_found = 0, stored_endian = 0, remove_obj_fn = 0x674f85 , sb_dirty_fn = 0x0, gc_control_fn = 0x0, use_header_file_size = 1, disable_lazy_load = 0, wide_tnodes_disabled = 0, disable_soft_del = 0, defered_dir_update = 0, always_check_erased = 0, disable_summary = 0, disable_bad_block_marking = 0}, drv = {drv_write_chunk_fn = 0x673 .... Yaffs /yaffs file tree information: 0x4096cac8 ├── dir {'name:/,obj_id:1,hdr_chunk:69,n_data_chunks:0,serial:2'} │ ├── dir {'name:b/,obj_id:258,hdr_chunk:82,n_data_chunks:0,serial:4'} │ │ ├── dir {'name:c/,obj_id:261,hdr_chunk:81,n_data_chunks:0,serial:1'} │ │ └── file {'name:3,obj_id:260,hdr_chunk:80,n_data_chunks:1,serial:2 file_size:5,stored:5'} │ │ └── file {'name:2,obj_id:259,hdr_chunk:76,n_data_chunks:1,serial:4 file_size:5,stored:5'} │ └── file {'name:1,obj_id:257,hdr_chunk:67,n_data_chunks:1,serial:2 file_size:6,stored:6'} │ ├── dir {'name:/,obj_id:2,hdr_chunk:0,n_data_chunks:0,serial:0'} Change-Id: Ib301fb673f944e15a2c4a72318d09427814736c0 Signed-off-by: guohao15 --- tools/pynuttx/nxgdb/fs.py | 149 ++++++++++++++++++++++++++++++++++---- 1 file changed, 133 insertions(+), 16 deletions(-) diff --git a/tools/pynuttx/nxgdb/fs.py b/tools/pynuttx/nxgdb/fs.py index 91c6eb8b67e..27be04c889d 100644 --- a/tools/pynuttx/nxgdb/fs.py +++ b/tools/pynuttx/nxgdb/fs.py @@ -27,6 +27,7 @@ from typing import Generator, Tuple, Union import gdb from . import utils +from .lists import NxList from .protocols import fs as p from .protocols.thread import Tcb @@ -162,7 +163,7 @@ def get_inode_name(inode: p.Inode): def inode_getpath(inode: p.Inode): - """get path fron inode""" + """get path from inode""" try: if not inode: return "" @@ -234,6 +235,18 @@ def foreach_file(tcb: Tcb): yield fd, file +def fstype_filter(fstype): + """Filter inodes by filesystem type""" + + def filter(item): + inode, path = item + if inode_gettype(inode) != InodeType.MOUNTPT: + return False + return get_fstype(inode) == fstype + + return filter + + class Fdinfo(gdb.Command): """Dump fd info information of process""" @@ -546,10 +559,10 @@ class InfoRomfs(gdb.Command): volume_size = mpt.rm_volsize xip_base = mpt.rm_xipbase buffer_base = mpt.rm_buffer - gdb.write( + print( f" HW sector size: {sector_size} HW sector number: {sector_num}\n" f" Volume size: {volume_size} XIP_addr: {hex(xip_base)}" - f" Buffer_addr: {hex(buffer_base)}\n" + f" Buffer_addr: {hex(buffer_base)}" ) def dump_romfs_files(self, node, level=1, prefix="", maxlevel=4096): @@ -566,9 +579,9 @@ class InfoRomfs(gdb.Command): dirfix = "" name = node.rn_name.string(length=node.rn_namesize) - gdb.write( + print( f"{initial_indent}{name}{dirfix} offset:{node.rn_offset} next:{node.rn_next}" - f" size:{node.rn_size} child_count:{node.rn_count}\n" + f" size:{node.rn_size} child_count:{node.rn_count}" ) for child in utils.ArrayIterator(node.rn_child, node.rn_count): @@ -577,7 +590,7 @@ class InfoRomfs(gdb.Command): def dump_romfs_cache(self, node: Inode, path): mpt = node.i_private.cast(utils.lookup_type("struct romfs_mountpt_s").pointer()) root = mpt.rm_root.cast(utils.lookup_type("struct romfs_nodeinfo_s").pointer()) - gdb.write(f"Romfs {path} mount point information: {hex(mpt)}\n") + print(f"Romfs {path} mount point information: {hex(mpt)}") self.dump_romfs_mpt(mpt) self.dump_romfs_files(root) @@ -594,17 +607,121 @@ class InfoRomfs(gdb.Command): def invoke(self, args, from_tty): args = self.parse_arguments(gdb.string_to_argv(args)) - - def romfs_filter(item): - inode, path = item - if inode_gettype(inode) != InodeType.MOUNTPT: - return False + nodes = filter(fstype_filter("romfs"), foreach_inode()) + for node, path in nodes: if args and args.path and path != args.path: - return False + continue + self.dump_romfs_cache(node, path) + + +class InfoYaffs(gdb.Command): + """Show yaffs cache information""" + + YAFFS_FILETYPE_MAP = { + 0: "yaffs_UNKNOWN_var", + 1: "yaffs_file_var", + 2: "yaffs_symlink_var", + 3: "yaffs_dir_var", + 4: "yaffs_hardlink_var", + 5: "yaffs_SPECIAL_var", + } - fstype = get_fstype(inode) - return fstype == "romfs" + def __init__(self): + if utils.get_symbol_value("CONFIG_FS_YAFFS"): + super().__init__("info yaffs", gdb.COMMAND_USER) + + def parse_arguments(self, argv): + parser = argparse.ArgumentParser(description=gdb.__doc__) + parser.add_argument( + "-P", + "--path", + type=str, + default=None, + help="set the yaffs path to be dumped", + ) + + try: + args = parser.parse_args(argv) + except SystemExit: + return None + + return args - nodes = filter(romfs_filter, foreach_inode()) + def dump_yaffs_files(self, node, level=1, prefix="", maxlevel=4096): + if level > maxlevel: + return + + file_type = self.YAFFS_FILETYPE_MAP[int(node.variant_type)] + if file_type == "yaffs_dir_var": + initial_indent = prefix + "├── " + newprefix = prefix + "│ " + dirfix = "/" + moreinfo = "" + elif file_type == "yaffs_file_var": + initial_indent = prefix + "└── " + newprefix = prefix + " " + dirfix = "" + file = node.variant.cast(utils.lookup_type("struct yaffs_file_var")) + file_size = file.file_size + stored = file.stored_size + moreinfo = f" file_size:{file_size},stored:{stored}" + else: + initial_indent = prefix + "└── " + newprefix = prefix + " " + dirfix = "" + moreinfo = "" + + obj_id = node.obj_id + short_name = node.short_name.string(length=16).rstrip("\0") + if short_name == "": + short_name = "(null)" + hdr_chunk = node.hdr_chunk + n_data_chunks = node.n_data_chunks + serial = str(node.serial).split(" ")[0] + baseinfo = { + f"name:{short_name}{dirfix},obj_id:{obj_id},hdr_chunk:{hdr_chunk}," + f"n_data_chunks:{n_data_chunks},serial:{serial}{moreinfo}" + } + + print(f"{initial_indent}{file_type.rsplit('_',2)[1]} {baseinfo}") + if file_type == "yaffs_dir_var": + head = node.variant.cast(utils.lookup_type("struct yaffs_dir_var")) + for siblings in NxList(head.children, "struct yaffs_obj", "siblings"): + self.dump_yaffs_files(siblings, level + 1, newprefix, maxlevel) + + def dump_yaffs_mpt(self, mpt): + geo = mpt.geo.cast(utils.lookup_type("struct mtd_geometry_s")) + dev = mpt.dev.cast(utils.lookup_type("struct yaffs_dev").pointer()) + blksize = geo.blocksize + erasesize = geo.erasesize + erasecount = geo.neraseblocks + print(f" Block size:{blksize} Erase size:{erasesize} Erase count:{erasecount}") + print(f"Dump yaffs_dev: {hex(dev)}") + print(dev.dereference().format_string(pretty_structs=True, styling=True)) + + def dump_yaffs_cache(self, node: Inode, path): + mpt = node.i_private.cast(utils.lookup_type("struct yaffs_mountpt_s").pointer()) + dev = mpt.dev.cast(utils.lookup_type("struct yaffs_dev").pointer()) + root = dev.root_dir.cast(utils.lookup_type("struct yaffs_obj").pointer()) + print(f"Yaffs {path} mount point information: {hex(mpt)}") + self.dump_yaffs_mpt(mpt) + print(f"Yaffs {path} file tree information: {hex(root)}") + self.dump_yaffs_files(root) + + def diagnose(self, *args, **kwargs): + output = gdb.execute("info yaffs", to_string=True) + return { + "title": "Yaffs cache information", + "summary": "Yaffs information dump", + "command": "info Yaffs", + "result": "info", + "message": output or "No yaffs information", + } + + def invoke(self, args, from_tty): + args = self.parse_arguments(gdb.string_to_argv(args)) + nodes = filter(fstype_filter("yaffs"), foreach_inode()) for node, path in nodes: - self.dump_romfs_cache(node, path) + if args and args.path and path != args.path: + continue + self.dump_yaffs_cache(node, path) -- Gitee From 21769fb60a0fa9b1654bc7e19e998a263c3813bb Mon Sep 17 00:00:00 2001 From: yinshengkai Date: Wed, 5 Mar 2025 23:36:03 +0800 Subject: [PATCH 142/235] pynuttx: add etm trace parse tools VELAPLATFO-55359 Change-Id: Ib973c4d886e26d6646165a2947fcf88de5a7e8f7 Signed-off-by: yinshengkai --- tools/pynuttx/etm2human.py | 211 +++ tools/pynuttx/etm2trace.py | 294 ++++ tools/pynuttx/nxelf/elf.py | 136 +- tools/pynuttx/nxtrace/etmv4_decoder.py | 1944 +++++++++++++++++++++++ tools/pynuttx/nxtrace/perfetto_trace.py | 93 ++ tools/pynuttx/requirements.txt | 2 + 6 files changed, 2678 insertions(+), 2 deletions(-) create mode 100755 tools/pynuttx/etm2human.py create mode 100755 tools/pynuttx/etm2trace.py create mode 100644 tools/pynuttx/nxtrace/etmv4_decoder.py diff --git a/tools/pynuttx/etm2human.py b/tools/pynuttx/etm2human.py new file mode 100755 index 00000000000..2b0c54c8238 --- /dev/null +++ b/tools/pynuttx/etm2human.py @@ -0,0 +1,211 @@ +#!/usr/bin/env python3 +############################################################################ +# tools/pynuttx/etm2human.py +# +# SPDX-License-Identifier: Apache-2.0 +# +# Licensed to the Apache Software Foundation (ASF) under one or more +# contributor license agreements. See the NOTICE file distributed with +# this work for additional information regarding copyright ownership. The +# ASF licenses this file to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance with the +# License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# +############################################################################ + +import argparse +import logging +import sys + +from nxtrace.etmv4_decoder import ( + ATOM_TYPE_E, + ETBStream, + ETMv4Decoder, + ETMv4Packet, + ETMv4PacketType, + decode_etb, +) + +log = logging.getLogger() + + +class ETM2Human: + + def emit(self, msg): + print(msg) + sys.stdout.flush() + + def trace_info(self, pkt: ETMv4Packet): + cc_enabled = pkt["cycle_count_enabled"] + cond_inst_enabled = pkt["conditional_non_branch_instruction_enabled"] + load_inst_enabled = pkt["load_instruction_enabled"] + store_inst_enabled = pkt["store_instruction_enabled"] + + self.emit( + f"TraceInfo - Cycle count {'enabled' if cc_enabled else 'disabled'},\n" + f" Tracing of conditional non-branch instruction {'enabled' if cond_inst_enabled else 'disabled'},\n" + f" {'NO' if not load_inst_enabled else ''} Explicit tracing of load instructions,\n" + f" {'NO' if not store_inst_enabled else ''} Explicit tracing of store instructions,\n" + f" p0_key = 0x{pkt['p0_key']:x},\n" + f" curr_spec_depth = {pkt['curr_spec_depth']},\n" + f" cc_threshold = 0x{pkt['cc_threshold']:x}" + ) + + def trace_on(self, pkt: ETMv4Packet): + self.emit("TraceOn - A discontinuity in the trace stream") + + def trace_off(self, pkt: ETMv4Packet): + self.emit("TraceOff - A discontinuity in the trace stream") + + def trace_discard(self, pkt: ETMv4Packet): + self.emit("Discard") + + def trace_overflow(self, pkt: ETMv4Packet): + self.emit("Overflow") + + def trace_ts(self, pkt: ETMv4Packet): + timestamp = hasattr(pkt, "timestamp") and pkt["timestamp"] or 0 + self.emit(f"Timestamp - {timestamp}") + if hasattr(pkt, "cycle"): + self.emit( + f" (number of cycles between the most recent Cycle Count element {pkt['cycle']})" + ) + + def trace_exception(self, pkt: ETMv4Packet): + self.emit( + f"Exception - exception type {pkt['exception_type_name']}, address 0x{pkt['address']:016x}" + ) + + def trace_exception_return(self, pkt: ETMv4Packet): + self.emit("Exception return") + + def trace_cc(self, pkt: ETMv4Packet): + if hasattr(pkt, "unknown"): + self.emit("Cycle count - unknown") + else: + self.emit(f"Cycle count - {pkt['cycle']}") + + def trace_commit(self, pkt: ETMv4Packet): + self.emit(f"Commit - {pkt['commit']}") + + def trace_cancel(self, pkt: ETMv4Packet): + self.emit(f"Cancel - {pkt['cancel']}") + + def trace_mispredict(self, pkt: ETMv4Packet): + self.emit("Mispredict") + + def trace_cond_inst(self, pkt: ETMv4Packet): + log.warning("Conditional instruction is not implemented yet") + + def trace_cond_flush(self, pkt: ETMv4Packet): + self.emit("Conditional flush") + + def trace_cond_result(self, pkt: ETMv4Packet): + log.warning("Conditional result is not implemented yet") + + def trace_context(self, pkt: ETMv4Packet): + setattr(self, "sixty_four_bit", pkt["sixty_four_bit"]) + setattr(self, "ex_level", pkt["ex_level"]) + setattr(self, "security", pkt["security"]) + + self.emit(f"Context - Context ID = 0x{pkt['context_id']:x},") + self.emit(f" VMID = 0x{pkt['vmid']:x},") + self.emit(f" Exception level = EL{pkt['ex_level']},") + self.emit(f" Security = {'S' if pkt['security'] else 'NS'},") + self.emit(f" {64 if pkt['sixty_four_bit'] else 32}-bit instruction") + + def trace_address(self, pkt: ETMv4Packet): + if self.sixty_four_bit: + self.emit( + f"Address - Instruction address 0x{pkt['address']:016x}, Instruction set Aarch64" + ) + else: + if pkt["instruction_set"]: + self.emit( + f"Address - Instruction address 0x{pkt['address']:016x}, Instruction set Aarch32 (Thumb)" + ) + else: + self.emit( + f"Address - Instruction address 0x{pkt['address']:016x}, Instruction set Aarch32 (ARM)" + ) + + def trace_atom(self, pkt: ETMv4Packet): + self.emit(f"ATOM - {'E' if pkt['atom_type'] == ATOM_TYPE_E else 'N'}") + + def trace_q(self, pkt: ETMv4Packet): + if pkt["cycle"]: + self.emit(f"Q - {pkt['cycle']} of instructions") + else: + self.emit("Q - UNKNOWN of instructions") + + etm2human_decoder = { + ETMv4PacketType.TRACE_INFO: trace_info, + ETMv4PacketType.TRACE_ON: trace_on, + ETMv4PacketType.TRACE_OFF: trace_off, + ETMv4PacketType.DISCARD: trace_discard, + ETMv4PacketType.OVERFLOW: trace_overflow, + ETMv4PacketType.TIMESTAMP: trace_ts, + ETMv4PacketType.EXCEPTION: trace_exception, + ETMv4PacketType.EXCEPTION_RETURN: trace_exception_return, + ETMv4PacketType.CYCLE_COUNT: trace_cc, + ETMv4PacketType.COMMIT: trace_commit, + ETMv4PacketType.CANCEL: trace_cancel, + ETMv4PacketType.MISPREDICT: trace_mispredict, + ETMv4PacketType.COND_INST: trace_cond_inst, + ETMv4PacketType.COND_FLUSH: trace_cond_flush, + ETMv4PacketType.COND_RESULT: trace_cond_result, + ETMv4PacketType.CONTEXT: trace_context, + ETMv4PacketType.ADDRESS: trace_address, + ETMv4PacketType.ATOM: trace_atom, + ETMv4PacketType.Q: trace_q, + } + + def decode_trace(self, pkt: ETMv4Packet): + self.etm2human_decoder[pkt.type](self, pkt) + + +def parse_args(): + parser = argparse.ArgumentParser() + + parser.add_argument( + "-i", "--input", required=True, type=str, help="Give the trace file" + ) + parser.add_argument( + "-u", + "--unaligned", + action="store_true", + help="Trace is unaligned and needs to be aligned by frame synchronization packet", + ) + parser.add_argument( + "-d", + "--debug", + type=str, + choices=["debug", "info", "warning", "error", "critical"], + default="warning", + help="Set the debug level", + ) + + return parser.parse_args() + + +def main(): + args = parse_args() + logger = logging.getLogger() + logger.setLevel(args.debug.upper()) + + etm2human = ETM2Human() + etm_decoder = ETMv4Decoder() + stream = ETBStream(etm_decoder, args.input, etm2human.decode_trace) + decode_etb(stream, args.unaligned) + + +if __name__ == "__main__": + main() diff --git a/tools/pynuttx/etm2trace.py b/tools/pynuttx/etm2trace.py new file mode 100755 index 00000000000..34ed3bee00a --- /dev/null +++ b/tools/pynuttx/etm2trace.py @@ -0,0 +1,294 @@ +#!/usr/bin/env python3 +############################################################################ +# tools/pynuttx/etm2trace.py +# +# SPDX-License-Identifier: Apache-2.0 +# +# Licensed to the Apache Software Foundation (ASF) under one or more +# contributor license agreements. See the NOTICE file distributed with +# this work for additional information regarding copyright ownership. The +# ASF licenses this file to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance with the +# License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# +############################################################################ + +import argparse +import logging + +from nxelf.elf import AngrElf +from nxtrace.etmv4_decoder import ( + ATOM_TYPE_E, + ATOM_TYPE_N, + ETBStream, + ETMv4Decoder, + ETMv4Packet, + ETMv4PacketType, + decode_etb, +) +from nxtrace.perfetto_trace import PerfettoTrace + +log = logging.getLogger(__name__) + + +class ETMTimestamp: + def __init__(self, freq: int = 1000000000): + self.freq = freq + self.ts = 0 + + def cycle2ts(self, cycle: int): + return int(cycle * 1000000000 / self.freq) + + def update(self, cycle: int = None, ts: int = None): + if cycle: + self.ts += self.cycle2ts(cycle) + elif ts: + self.ts = ts + else: + log.debug("Cycle or ts not provided! timestamp will not be updated") + return + + log.debug(f"timestamp - {self.ts} ns") + + def compensate(self, bb): + cycle = len(bb.block.capstone.insns) if bb.block else 0 + self.ts += self.cycle2ts(cycle) + log.debug(f"Compensate - {self.ts} ns") + + def __str__(self): + return str(self.ts) + + +class BasicBlock: + def __init__(self, elf, addr: int, timestamp: ETMTimestamp): + try: + self.elf = elf + self.addr = addr + self.timestamp = timestamp + self.symbol = elf.addr2sym(self.addr) + self.func = elf.addr2func(self.addr) + self.block = self.func.get_block(self.addr) + except Exception as e: + log.error(f"BasicBlock error: {self.addr:#08x} {e}") + self.block = None + + def is_endpoint(self): + for retblock in self.func.endpoints: + if self.addr >= retblock.addr and self.addr < retblock.addr + retblock.size: + return True + return False + + def is_entrypoint(self): + return self.func.startpoint.addr == self.addr + + def todict(self): + return { + "addr": hex(self.addr), + "timestamp": self.timestamp.ts if self.timestamp else 0, + "symbol": self.symbol, + "block_addr": hex(self.block.addr) if self.block else 0, + "block_size": self.block.size if self.block else 0, + } + + +class TimeLine: + last_symbol = None + symbol_uuid = dict() + + def __init__(self, ptrace): + self.ptrace = ptrace + + def uuid(self, symbol): + uuid = self.symbol_uuid.get(symbol, 0) + if not uuid: + uuid = self.ptrace.next_uuid() + self.ptrace.add_thread( + uuid=uuid, parent_uuid=0, tid=uuid, pid=1, name=symbol + ) + self.symbol_uuid[symbol] = uuid + + return uuid + + def trace_event(self, event, bb: BasicBlock): + self.ptrace.trace_event( + uuid=self.uuid(bb.symbol), + ts=bb.timestamp.ts, + type=event, + name=bb.symbol, + args=bb.todict(), + ) + + def parse(self, now_bb: BasicBlock, last_bb: BasicBlock = None): + if last_bb and last_bb.symbol != now_bb.symbol: + self.trace_event(self.ptrace.SLICE_END, last_bb) + self.trace_event(self.ptrace.SLICE_BEGIN, now_bb) + + +class CallStack: + executing_func = dict() + + def __init__(self, ptrace): + self.ptrace = ptrace + self.tid = ptrace.next_uuid() + self.ptrace.add_thread( + uuid=self.tid, parent_uuid=0, tid=self.tid, pid=0, name="MainThread" + ) + + def trace_event(self, event, bb: BasicBlock): + self.ptrace.trace_event( + uuid=self.tid, + ts=bb.timestamp.ts, + type=event, + name=bb.symbol, + args=bb.todict(), + ) + + def parse(self, now_bb: BasicBlock, last_bb: BasicBlock = None): + # If the last executed basic block is a function return point, an end event is generated + if last_bb and last_bb.is_endpoint(): + self.trace_event(self.ptrace.SLICE_END, last_bb) + self.executing_func.pop(last_bb.symbol, None) + + if now_bb.is_entrypoint() or not self.executing_func.get(now_bb.symbol): + # If the current basic block is a function entry point, a begin event is generated + # Or if the basic block is not a function entry, but it is not in + # the list of executed functions, it means that we have lost the function entry event. + # We immediately add one here. + self.trace_event(self.ptrace.SLICE_BEGIN, now_bb) + self.executing_func[now_bb.symbol] = [now_bb] + + +class ETM2Trace: + index = 0 + thumb_mode = False + bb = None + + def __init__(self, elf, parser: list = [], freq: int = 1000000000): + self.elf = elf + self.timestamp = ETMTimestamp(freq) + self.parser = parser + + def trace_cycle(self, pkt: ETMv4Packet): + self.timestamp.update(cycle=getattr(pkt, "cycle", None)) + + def trace_timestamp(self, pkt: ETMv4Packet): + self.timestamp.update( + ts=getattr(pkt, "timestamp", None), cycle=getattr(pkt, "cycle", None) + ) + + def register_parser(self, parser): + self.parser.append(parser) + + def execute_address(self, addr: int): + bb = BasicBlock(self.elf, addr, timestamp=self.timestamp) + log.debug(f"--> ts: {self.timestamp.ts} address - {bb.symbol}({addr:#08x})") + + # If the timestamp of the current basic block is the same as the timestamp of the last basic block, + # it means that the timestamp of the current basic block is not accurate, so we need to compensate it. + if self.bb and bb.timestamp.ts == self.bb.timestamp.ts: + self.timestamp.compensate(bb) + + for parser in self.parser: + parser.parse(bb, self.bb) + + self.bb = bb + + def trace_address(self, pkt: ETMv4Packet): + addr = pkt["address"] + self.thumb_mode = pkt["instruction_set"] + self.execute_address(addr | (0x1 if self.thumb_mode else 0)) + + def trace_atom(self, pkt: ETMv4Packet): + if self.bb: + try: + if pkt["atom_type"] == ATOM_TYPE_E: + next_addr = self.elf.get_block_next_address(self.bb.block) + elif pkt["atom_type"] == ATOM_TYPE_N: + next_addr = self.bb.addr + self.bb.block.size + + if next_addr: + self.execute_address(next_addr | (0x1 if self.thumb_mode else 0)) + + except Exception as e: + log.error(f"trace_atom parse failed: {self.bb.addr:#08x} {e}") + + etm2trace_decoder = { + ETMv4PacketType.TIMESTAMP: trace_timestamp, + ETMv4PacketType.ADDRESS: trace_address, + ETMv4PacketType.CYCLE_COUNT: trace_cycle, + ETMv4PacketType.ATOM: trace_atom, + } + + def decode_trace(self, pkt: ETMv4Packet): + decoder = self.etm2trace_decoder.get(pkt.type) + if decoder: + decoder(self, pkt) + + +def parse_arguments(): + parser = argparse.ArgumentParser(description="ETM2Trace Command Line Arguments") + parser.add_argument("-e", "--elf", type=str, required=True, help="ELF file path") + parser.add_argument( + "-i", "--input", type=str, required=True, help="Input file path" + ) + parser.add_argument( + "-o", "--output", type=str, default="perfetto_trace.pb", help="Output file path" + ) + parser.add_argument( + "-d", + "--debug", + type=str, + choices=["debug", "info", "warning", "error", "critical"], + default="warning", + help="Set the debug level", + ) + parser.add_argument( + "-m", + "--mode", + type=str, + nargs="+", + choices=["timeline", "callstack"], + help="Mode of operation", + ) + parser.add_argument( + "-f", "--freq", type=int, default=1000000000, help="Frequency of the trace" + ) + + return parser.parse_args() + + +def main(): + args = parse_arguments() + + logger = logging.getLogger() + logger.setLevel(args.debug.upper()) + logger = logging.getLogger("angr") + logger.setLevel(logging.WARNING) + + ptrace = PerfettoTrace(args.output) + + elf = AngrElf(args.elf) + + etm2trace = ETM2Trace(elf, freq=args.freq) + if "timeline" in args.mode: + etm2trace.register_parser(TimeLine(ptrace)) + if "callstack" in args.mode: + etm2trace.register_parser(CallStack(ptrace)) + + etm_decoder = ETMv4Decoder() + stream = ETBStream(etm_decoder, args.input, etm2trace.decode_trace) + decode_etb(stream, False) + + ptrace.flush() + + +if __name__ == "__main__": + main() diff --git a/tools/pynuttx/nxelf/elf.py b/tools/pynuttx/nxelf/elf.py index 3304a1c54e4..98a2ad67ec0 100644 --- a/tools/pynuttx/nxelf/elf.py +++ b/tools/pynuttx/nxelf/elf.py @@ -19,7 +19,13 @@ # ############################################################################ + +import hashlib +import importlib import logging +import os +import pickle +import sys import time from enum import IntEnum from typing import Tuple @@ -55,8 +61,7 @@ except ModuleNotFoundError as e: print(f"Error:{e}.\nPlease execute the following command to install dependencies:") print("pip install construct pyelftools cxxfilt lief ") -logging.basicConfig(level=logging.WARNING) -logger = logging.getLogger(__name__) +log = logging.getLogger(__name__) class TypeConflictError(Exception): @@ -494,3 +499,130 @@ class LiefELF: def get_pointer_size(self): return 8 if self.elf.abstract.header.is_64 else 4 + + +class AngrElf: + def __init__(self, elf: str): + try: + self.angr = importlib.import_module("angr") + self.capstone = importlib.import_module("capstone") + except Exception as e: + print( + f"Error:{e}.\nPlease execute the following command to install dependencies:" + ) + print("pip install angr capstone") + sys.exit(1) + + with open(elf, "rb") as f: + hash = hashlib.md5(f.read()).hexdigest() + + project_cache_path = f"{hash}.project" + cfg_cache_path = f"{hash}.cfg" + + self.project = self.load_save_cache( + project_cache_path, lambda: self.angr.Project(elf, auto_load_libs=False) + ) + self.cfg = self.load_save_cache( + cfg_cache_path, lambda: self.project.analyses.CFGFast() + ) + + for func in self.cfg.kb.functions.values(): + func._project = self.project + + def load_save_cache(self, file_path, func): + cache_path = f"{file_path}.pkl" + if os.path.exists(cache_path): + with open(cache_path, "rb") as f: + print(f"load cache {cache_path}") + return pickle.load(f) + else: + print(f"not found cache {cache_path}") + obj = func() + with open(cache_path, "wb") as f: + print(f"create cache {cache_path}") + pickle.dump(obj, f) + return obj + + def sym2addr(self, sym: str): + sym = self.cfg.kb.functions.floor_func(sym) + if sym: + return sym.addr + else: + return None + + def addr2sym(self, addr: int): + sym = self.cfg.kb.functions.floor_func(addr) + if sym: + return sym.name + else: + return f"0x{addr:08x}" + + def addr2func(self, addr: int): + addr = addr + sym = self.cfg.kb.functions.floor_func(addr) + if sym: + return self.cfg.kb.functions[sym.addr] + else: + return None + + def sym2func(self, sym: str): + addr = self.sym2addr(sym) + if addr: + return self.cfg.kb.functions[addr] + else: + return None + + def addr2block(self, addr: int): + addr = addr + sym = self.cfg.kb.functions.floor_func(addr) + if sym: + func = self.cfg.kb.functions[sym.addr] + for block in func._addr_to_block_node.values(): + if addr >= block.addr and addr < block.addr + block.size: + return block + else: + return None + + def print_block(self, block): + print(f"basic block: {hex(block.addr)}, size: {block.size}") + for insn in block.capstone.insns: + print(f" {hex(insn.address)}: {insn.mnemonic} {insn.op_str}") + if insn.group(self.capstone.CS_GRP_CALL): + print(f" call {hex(insn.operands[0].imm)}") + elif insn.group(self.capstone.CS_GRP_RET): + print(f" return {hex(insn.operands[0].imm)}") + elif insn.group(self.capstone.CS_GRP_INT): + print(f" interrupt {hex(insn.operands[0].imm)}") + elif insn.group(self.capstone.CS_GRP_BRANCH_RELATIVE): + target_addr = insn.operands[0].imm + target_function = self.cfg.kb.functions.floor_func(target_addr) + print( + f" conditional jump {hex(target_addr)} (target function: {target_function.name})" + ) + elif insn.group(self.capstone.CS_GRP_JUMP): + sub_function = self.cfg.kb.functions.floor_func(insn.operands[0].imm) + print( + f" unconditional jump {hex(insn.operands[0].imm)} (target function: {sub_function.name})" + ) + sys.stdout.flush() + + def print_function(self, function): + print(f"function: {function.name} {function.addr} {function.size}") + for block in function.blocks: + self.print_block(block) + + def get_block_next_address(self, block): + for insn in block.capstone.insns: + if insn.group(self.capstone.CS_GRP_BRANCH_RELATIVE): + try: + addr = insn.operands[0].imm + func = self.addr2func(addr) + if func: + next_block = func.get_block(addr) + return next_block.addr + except Exception as e: + log.error( + f"get_block_next_address failed: addr: {block.addr:#08x} {e}" + ) + return None + return None diff --git a/tools/pynuttx/nxtrace/etmv4_decoder.py b/tools/pynuttx/nxtrace/etmv4_decoder.py new file mode 100644 index 00000000000..56ef3507e67 --- /dev/null +++ b/tools/pynuttx/nxtrace/etmv4_decoder.py @@ -0,0 +1,1944 @@ +############################################################################ +# tools/pynuttx/nxtrace/etmv4_decoder.py +# +# SPDX-License-Identifier: Apache-2.0 +# +# Licensed to the Apache Software Foundation (ASF) under one or more +# contributor license agreements. See the NOTICE file distributed with +# this work for additional information regarding copyright ownership. The +# ASF licenses this file to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance with the +# License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# +############################################################################ + +import logging +from dataclasses import dataclass +from enum import Enum, auto + +log = logging.getLogger(__name__) + +ADDR_REG_IS_UNKNOWN = -1 +ADDR_REG_IS0 = 0 +ADDR_REG_IS1 = 1 + +ATOM_TYPE_E = 1 +ATOM_TYPE_N = 2 + + +class StreamState(Enum): + READING = 0 + SYNCING = 1 + INSYNC = 2 + OUTSYNC = 3 + DECODING = 4 + + +class ETMv4PacketType(Enum): + TRACE_INFO = auto() + TRACE_ON = auto() + TRACE_OFF = auto() + DISCARD = auto() + OVERFLOW = auto() + ATOM = auto() + Q = auto() + EXCEPTION = auto() + EXCEPTION_RETURN = auto() + ADDRESS = auto() + CONTEXT = auto() + BRANCH_FLUSH = auto() + FUNCTION_RETURN = auto() + TIMESTAMP = auto() + TIMESTAMP_MARK = auto() + CYCLE_COUNT = auto() + EVENT = auto() + COMMIT = auto() + CANCEL = auto() + MISPREDICT = auto() + COND_INST = auto() + COND_RESULT = auto() + COND_FLUSH = auto() + DATA_SYNC_MARKER = auto() + + +@dataclass +class ETMv4AddressRegister: + address: int + instruction_set: int + + +class ETMv4Tracer: + def __init__(self): + self.info = 0 + self.condtype = 0 + self.commopt = 0 + self.timestamp = 0 + self.address_register = [ETMv4AddressRegister(0, 1) for _ in range(3)] + self.context_id = 0 + self.vmid = 0 + self.ex_level = 0 + self.security = 0 + self.sixty_four_bit = 0 + self.curr_spec_depth = 0 + self.p0_key = 0 + self.cond_c_key = 0 + self.cond_r_key = 0 + self.p0_key_max = 0 + self.cond_key_max_incr = 0 + self.max_spec_depth = 0 + self.cc_threshold = 0 + + def set_address_register(self, n, address): + self.address_register[n].address = address + + def set_address_register_IS(self, n, instruction_set): + self.address_register[n].instruction_set = instruction_set + + def reset_address_register(self): + self.address_register[0].address = 0 + self.address_register[0].instruction_set = 1 + self.address_register[1].address = 0 + self.address_register[1].instruction_set = 1 + self.address_register[2].address = 0 + self.address_register[2].instruction_set = 1 + + +class ETMv4Packet: + def __init__(self, pkt_type, raw_data: bytes = b""): + self.type = pkt_type + self.rawdata = raw_data + + def __getitem__(self, key): + if hasattr(self, key): + return getattr(self, key) + else: + raise KeyError(f"Attribute '{key}' not found") + + +class ETBStream: + def __init__(self, etm_decoder, input_file=None, trace_decode=None): + self.state = StreamState.READING + self.tracer = ETMv4Tracer() + self.decoder = etm_decoder + self.buff = bytearray() + self.tracer.decoder = trace_decode + if input_file: + with open(input_file, "rb") as f: + self.buff = memoryview(f.read()) + + def copy(self): + new_stream = ETBStream(self.decoder) + new_stream.state = self.state + new_stream.tracer = self.tracer + new_stream.decoder = self.decoder + return new_stream + + +class TracePacketMeta(type): + def __new__(cls, name, bases, dct): + # Automatically create decode function if not provided + if "decode" not in dct: + dct["decode"] = lambda self, data, stream: len(data) + return super().__new__(cls, name, bases, dct) + + +class TracePacket(metaclass=TracePacketMeta): + def __init__(self, mask, val, decode_func): + self.mask = mask + self.val = val + self.decode_func = decode_func + self.name = decode_func.__name__[7:] + + def decode(self, data, stream): + return self.decode_func(data, stream) + + +def tracer_trace_info( + tracer: ETMv4Tracer, plctl: int, info: int, key: int, spec: int, cyct: int +): + tracer.reset_address_register() + + tracer.info = info + tracer.p0_key = key + tracer.curr_spec_depth = spec + tracer.cc_threshold = cyct + + log.info( + f"TraceInfo - Cycle count {'enabled' if tracer.info & 1 else 'disabled'},\n" + f" Tracing of conditional non-branch instruction {'enabled' if tracer.info & 0x0E else 'disabled'},\n" + f" {'NO' if not tracer.info & 0x10 else ''} Explicit tracing of load instructions,\n" + f" {'NO' if not tracer.info & 0x20 else ''} Explicit tracing of store instructions,\n" + f" p0_key = 0x{key:x},\n" + f" curr_spec_depth = {spec},\n" + f" cc_threshold = 0x{cyct:x}" + ) + + packet = ETMv4Packet(ETMv4PacketType.TRACE_INFO) + setattr(packet, "cycle_count_enabled", tracer.info & 1) + setattr(packet, "conditional_non_branch_instruction_enabled", tracer.info & 0x0E) + setattr(packet, "load_instruction_enabled", tracer.info & 0x10) + setattr(packet, "store_instruction_enabled", tracer.info & 0x20) + setattr(packet, "p0_key", tracer.p0_key) + setattr(packet, "curr_spec_depth", tracer.curr_spec_depth) + setattr(packet, "cc_threshold", tracer.cc_threshold) + tracer.decoder(packet) + return tracer + + +def tracer_trace_on(tracer: ETMv4Tracer): + packet = ETMv4Packet(ETMv4PacketType.TRACE_ON) + tracer.decoder(packet) + log.info("TraceOn - A discontinuity in the trace stream") + + +def tracer_trace_off(tracer: ETMv4Tracer): + packet = ETMv4Packet(ETMv4PacketType.TRACE_OFF) + tracer.decoder(packet) + log.info("[TraceOff - A discontinuity in the trace stream]") + return tracer + + +def tracer_discard(tracer: ETMv4Tracer): + packet = ETMv4Packet(ETMv4PacketType.DISCARD) + tracer.decoder(packet) + log.info("Discard") + tracer_cond_flush(tracer) + tracer.curr_spec_depth = 0 + + +def tracer_overflow(tracer: ETMv4Tracer): + packet = ETMv4Packet(ETMv4PacketType.OVERFLOW) + tracer.decoder(packet) + log.info("Discard") + tracer_cond_flush(tracer) + tracer.curr_spec_depth = 0 + + +def tracer_ts( + tracer: ETMv4Tracer, timestamp: int, have_cc: int, cycle: int, nr_replace: int +): + packet = ETMv4Packet(ETMv4PacketType.TIMESTAMP) + if timestamp: + tracer.timestamp &= ~((1 << nr_replace) - 1) + tracer.timestamp |= timestamp + setattr(packet, "timestamp", tracer.timestamp) + + log.info(f"Timestamp - {tracer.timestamp}") + if have_cc: + setattr(packet, "cycle", cycle) + log.info( + f" (number of cycles between the most recent Cycle Count element {cycle})" + ) + + tracer.decoder(packet) + + +def tracer_exception(tracer: ETMv4Tracer, pkt_type: int): + exp_name = [ + "PE reset", + "Debug halt", + "Call", + "Trap", + "System error", + None, + "Inst debug", + "Data debug", + None, + None, + "Alignment", + "Inst fault", + "Data fault", + None, + "IRQ", + "FIQ", + ] + + exp_name = ( + exp_name[pkt_type] + if pkt_type < len(exp_name) and exp_name[pkt_type] + else "Reserved" + ) + log.info( + f"Exception - exception type {exp_name}, address 0x{tracer.address_register[0].address:016x}" + ) + packet = ETMv4Packet(ETMv4PacketType.EXCEPTION) + setattr(packet, "exception_type", pkt_type) + setattr( + packet, + "exception_type_name", + ( + exp_name[pkt_type] + if (pkt_type < len(exp_name) and exp_name[pkt_type]) + else "Reserved" + ), + ) + setattr(packet, "address", tracer.address_register[0].address) + tracer.decoder(packet) + tracer_cond_flush(tracer) + + if tracer.p0_key_max: + tracer.p0_key += 1 + tracer.p0_key %= tracer.p0_key_max + + tracer.curr_spec_depth += 1 + if not tracer.max_spec_depth or (tracer.curr_spec_depth > tracer.max_spec_depth): + tracer_commit(tracer, 1) + + +def tracer_exception_return(tracer: ETMv4Tracer): + packet = ETMv4Packet(ETMv4PacketType.EXCEPTION_RETURN) + tracer.decoder(packet) + log.info("Exception return") + # FIXME: for ARMv6-M and ARMv7-M PEs, exception_return is a P0 element + + +def tracer_cc(tracer: ETMv4Tracer, unknown: int, count: int): + packet = ETMv4Packet(ETMv4PacketType.CYCLE_COUNT) + if unknown: + log.info("Cycle count - unknown") + setattr(packet, "unknown", 1) + else: + cc = count + tracer.cc_threshold + log.info(f"Cycle count - {cc}") + setattr(packet, "cycle", cc) + tracer.decoder(packet) + + +def tracer_commit(tracer: ETMv4Tracer, commit: int): + log.info(f"Commit - {commit}") + tracer.curr_spec_depth -= commit + packet = ETMv4Packet(ETMv4PacketType.COMMIT) + setattr(packet, "commit", commit) + tracer.decoder(packet) + + +def tracer_cancel(tracer: ETMv4Tracer, mispredict: int, cancel: int): + log.info(f"Cancel - {cancel}") + tracer.curr_spec_depth -= cancel + + if tracer.p0_key_max: + tracer.p0_key -= cancel + tracer.p0_key %= tracer.p0_key_max + + if mispredict: + tracer_mispredict(tracer, 0) + tracer_cond_flush(tracer) + + +def tracer_mispredict(tracer: ETMv4Tracer, param: int): + if param == 0: + pass + elif param == 1: + tracer_atom(tracer, ATOM_TYPE_E) + elif param == 2: + tracer_atom(tracer, ATOM_TYPE_E) + tracer_atom(tracer, ATOM_TYPE_E) + elif param == 3: + tracer_atom(tracer, ATOM_TYPE_N) + else: + log.info(f"Invalid param ({param})") + + packet = ETMv4Packet(ETMv4PacketType.MISPREDICT) + setattr(packet, "param", param) + tracer.decoder(packet) + log.info("Mispredict") + + +def tracer_cond_inst(tracer: ETMv4Tracer, format: int, param1: int, param2: int): + if tracer.cond_key_max_incr == 0: + log.info( + "cond_key_max_incr MUST NOT be zero for conditional instruction elements." + ) + return + + if format == 1: + key = param1 + if __is_cond_key_special(tracer, key): + tracer.cond_c_key += 1 + tracer.cond_c_key %= tracer.cond_key_max_incr + else: + tracer.cond_c_key = key + log.info(f"Conditional instruction - C key = {key}") + + elif format == 2: + ci = param1 + if ci == 0: + tracer.cond_c_key += 1 + tracer.cond_c_key %= tracer.cond_key_max_incr + log.info(f"Conditional instruction - C key = {tracer.cond_c_key}") + elif ci == 1: + log.info(f"Conditional instruction - C key = {tracer.cond_c_key}") + elif ci == 2: + tracer.cond_c_key += 1 + tracer.cond_c_key %= tracer.cond_key_max_incr + log.info(f"Conditional instruction - C key = {tracer.cond_c_key}") + else: + log.info(f"Invalid CI ({ci})") + + elif format == 3: + z = param1 + num = param2 + for _ in range(num): + tracer.cond_c_key += 1 + tracer.cond_c_key %= tracer.cond_key_max_incr + log.info(f"Conditional instruction - C key = {tracer.cond_c_key}") + if z: + log.info(f"Conditional instruction - C key = {tracer.cond_c_key}") + + else: + log.info(f"Invalid format ({format})") + + +def tracer_cond_flush(tracer: ETMv4Tracer): + log.info("Conditional flush") + packet = ETMv4Packet(ETMv4PacketType.COND_FLUSH) + tracer.decoder(packet) + return tracer + + +def tracer_atom(tracer: ETMv4Tracer, atom_type): + + if atom_type == ATOM_TYPE_E: + log.info("ATOM - E") + elif atom_type == ATOM_TYPE_N: + log.info("ATOM - N") + else: + log.info(f"Invalid ATOM type ({atom_type})") + return + + packet = ETMv4Packet(ETMv4PacketType.ATOM) + setattr(packet, "atom_type", atom_type) + tracer.decoder(packet) + if tracer.p0_key_max: + tracer.p0_key += 1 + tracer.p0_key %= tracer.p0_key_max + + tracer.curr_spec_depth += 1 + if not tracer.max_spec_depth or (tracer.curr_spec_depth > tracer.max_spec_depth): + tracer_commit(tracer, 1) + + +def __is_cond_key_special(tracer: ETMv4Tracer, key: int): + return key >= tracer.cond_key_max_incr + + +def tracer_q(tracer: ETMv4Tracer, count: int): + if count: + log.info(f"Q - {count} of instructions") + else: + log.info("Q - UNKNOWN of instructions") + + packet = ETMv4Packet(ETMv4PacketType.Q) + setattr(packet, "cycle", count) + tracer.decoder(packet) + + if tracer.p0_key_max: + tracer.p0_key += 1 + tracer.p0_key %= tracer.p0_key_max + + tracer.curr_spec_depth += 1 + if not tracer.max_spec_depth or (tracer.curr_spec_depth > tracer.max_spec_depth): + tracer_commit(tracer, 1) + + +def __interpret_tokens(tracer: ETMv4Tracer, tokens: int, pos: int): + if pos % 2: + log.info(f"Invalid pos ({pos})") + return pos + 1 + + if tracer.condtype: + token = (tokens >> pos) & 0x0F + if (token & 0x03) == 0x03: + return pos + 2 + else: + if token == 0x0F: + return 0 + else: + return pos + 4 + else: + token = (tokens >> pos) & 0x03 + if token == 3: + # /* NULL, no R element indicated */ + return 0 + else: + return pos + 2 + + +def tracer_cond_result( + tracer: ETMv4Tracer, format: int, param1: int, param2: int, param3: int +): + cond_result_token_apsr = [ + "C flag set", + "N flag set", + "Z and C flags set", + "N and C flags set", + "unknown", + "unknown", + "unknown", + "No flag set", + "unknown", + "unknown", + "unknown", + "Z flag set", + "unknown", + "unknown", + "unknown", + "unknown", + ] + + cond_result_token_pass_fail = [ + "failed the condition code check", + "passed the condition code check", + "don't know the result of the condition code check", + ] + + MAX_TOKENS_POS = 12 + + if tracer.cond_key_max_incr == 0: + log.info( + "cond_key_max_incr MUST NOT be zero for conditional instruction elements." + ) + return + + if format == 1: + key = param1 + ci = param2 + result = param3 + if __is_cond_key_special(tracer, key): + tracer.cond_r_key += 1 + tracer.cond_r_key %= tracer.cond_key_max_incr + else: + tracer.cond_r_key = key + if ci: + while tracer.cond_c_key == tracer.cond_r_key: + tracer_cond_inst(tracer, 3, 0, 1) + if tracer.condtype: + log.info( + f"Conditional result - R key = {key}, APSR_V = {result & 0x01}," + f"APSR_C = {result & 0x02}, APSR_Z = {result & 0x04}, APSR_N = {result & 0x08}" + ) + else: + log.info( + f"Conditional result - R key = {key}, {'passed' if result else 'failed'} the condition code check" + ) + + elif format == 2: + k = param1 & 0x01 + token = param2 & 0x03 + tracer.cond_r_key += 1 + k + tracer.cond_r_key %= tracer.cond_key_max_incr + while tracer.cond_c_key == tracer.cond_r_key: + tracer_cond_inst(tracer, 3, 0, 1) + if tracer.condtype: + log.info( + f"Conditional result - R key = {tracer.cond_r_key}, APSR indication: {cond_result_token_apsr[token]}" + ) + else: + log.info( + f"Conditional result - R key = {tracer.cond_r_key}, {cond_result_token_pass_fail[token]}" + ) + + elif format == 3: + tokens = param1 & 0x0FFF + pos = 0 + while True: + next_pos = __interpret_tokens(tracer, tokens, pos) + if next_pos: + token = (tokens & ((1 << next_pos) - 1)) >> pos + if tracer.condtype: + log.info( + f"Conditional result - R key = {tracer.cond_r_key}, APSR indication: {cond_result_token_apsr[token]}" + ) + else: + log.info( + f"Conditional result - R key = {tracer.cond_r_key}, {cond_result_token_pass_fail[token]}" + ) + pos = next_pos + if next_pos == 0 or pos >= MAX_TOKENS_POS: + break + + elif format == 4: + token = param1 & 0x03 + tracer.cond_r_key -= 1 + tracer.cond_r_key %= tracer.cond_key_max_incr + if tracer.condtype: + log.info( + f"Conditional result - R key = {tracer.cond_r_key}, APSR indication: {cond_result_token_apsr[token]}" + ) + else: + log.info( + f"Conditional result - R key = {tracer.cond_r_key}, {cond_result_token_pass_fail[token]}" + ) + + else: + log.info(f"Invalid format ({format})") + + +def tracer_context( + tracer: ETMv4Tracer, + p: int, + el: int, + sf: int, + ns: int, + v: int, + vmid: int, + c: int, + contextid: int, +): + if p: + tracer.ex_level = el + tracer.sixty_four_bit = sf + tracer.security = not ns + if v: + tracer.vmid = vmid + if c: + tracer.context_id = contextid + + packet = ETMv4Packet(ETMv4PacketType.CONTEXT) + setattr(packet, "context_id", contextid) + setattr(packet, "vmid", vmid) + setattr(packet, "ex_level", el) + setattr(packet, "security", not ns) + setattr(packet, "sixty_four_bit", sf) + tracer.decoder(packet) + + log.info(f"Context - Context ID = 0x{tracer.context_id:x},") + log.info(f" VMID = 0x{tracer.vmid:x},") + log.info(f" Exception level = EL{tracer.ex_level},") + log.info(f" Security = {'S' if tracer.security else 'NS'},") + log.info(f" {64 if tracer.sixty_four_bit else 32}-bit instruction") + + +def tracer_address(tracer: ETMv4Tracer): + address = tracer.address_register[0].address + instruction_set = tracer.address_register[0].instruction_set + + if tracer.sixty_four_bit: + log.info( + f"Address - Instruction address 0x{address:016x}, Instruction set Aarch64" + ) + else: + if instruction_set: + log.info( + f"Address - Instruction address 0x{address:016x}, Instruction set Aarch32 (ARM)" + ) + else: + log.info( + f"Address - Instruction address 0x{address:016x}, Instruction set Aarch32 (ç)" + ) + + packet = ETMv4Packet(ETMv4PacketType.ADDRESS) + setattr(packet, "address", address) + setattr(packet, "instruction_set", instruction_set) + tracer.decoder(packet) + + +# Define all trace packets using the metaclass +def decode_extension(data, stream): + index = 1 + cnt = 0 + + if len(data) <= 1: + log.error("Not enough data to decode extension packet") + return -1 + + if data[index] == 0: + if 11 > len(data): + return -1 + + # async + while cnt < 11 and index < len(stream.buff): + if cnt == 10 and data[index] != 0x80: + break + if cnt != 10 and data[index] != 0: + break + cnt += 1 + index += 1 + + if cnt != 11: + log.error("Payload bytes of async are not correct") + log.error("Invalid async packet") + return -1 + + log.debug("[async]") + + elif data[index] == 3: + # discard + index += 1 + log.debug("[discard]") + # Assuming tracer_discard is a method of the tracer object + tracer_discard(stream.tracer) + + elif data[index] == 5: + # overflow + index += 1 + log.debug("[overflow]") + # Assuming tracer_overflow is a method of the tracer object + tracer_overflow(stream.tracer) + + else: + log.error("First payload byte of async is not correct") + log.error("Invalid async packet") + return -1 + + return index + + +def decode_trace_info(data, stream: ETBStream): + index = 1 + plctl = 0 + info = 0 + key = 0 + spec = 0 + cyct = 0 + + # Decode PLCTL + for i in range(4): + if index >= len(data): + break + byte = data[index] + plctl |= (byte & ~0x80) << (7 * i) + index += 1 + if not (byte & 0x80): + break + + if i >= 1: + log.error("More than 1 PLCTL field in the trace info packet") + return -1 + + # Decode INFO + if plctl & 1: + for i in range(4): + byte = data[index] + info |= (byte & ~0x80) << (7 * i) + index += 1 + if not (byte & 0x80): + break + if i >= 1: + log.error("More than 1 INFO field in the trace info packet") + return -1 + + # Decode KEY + if plctl & 2: + for i in range(4): + byte = data[index] + key |= (byte & ~0x80) << (7 * i) + index += 1 + if not (byte & 0x80): + break + if i >= 4: + log.error("More than 4 KEY fields in the trace info packet") + return -1 + + # Decode SPEC + if plctl & 4: + for i in range(4): + byte = data[index] + spec |= (byte & ~0x80) << (7 * i) + index += 1 + if not (byte & 0x80): + break + if i >= 4: + log.error("More than 4 SPEC fields in the trace info packet") + return -1 + + # Decode CYCT + if plctl & 8: + for i in range(2): + byte = data[index] + cyct |= (byte & ~0x80) << (7 * i) + index += 1 + if not (byte & 0x80): + break + if i >= 2: + log.error("More than 2 CYCT fields in the trace info packet") + return -1 + + log.debug( + f"[trace info] plctl = 0x{plctl:X}, info = 0x{info:X}, key = 0x{key:X}, spec = {spec}, cyct = 0x{cyct:X}" + ) + + if stream.state.value >= StreamState.INSYNC.value: + tracer_trace_info(stream.tracer, plctl, info, key, spec, cyct) + + return index + + +def decode_trace_on(data, stream): + log.debug("[trace on]") + tracer_trace_on(stream.tracer) + return 1 + + +def decode_timestamp(data, stream): + nr_replace = 0 + index = 1 + ts = 0 + count = 0 + + # Decode timestamp + for i in range(10): + byte = data[index] + index += 1 + ts |= (byte & ~0x80) << (7 * i) + if index != 9: + nr_replace += 7 + else: + nr_replace += 8 + if (index != 9) and not (byte & 0x80): + break + + # Decode cycle count if present + if data[0] & 1: + for i in range(3): + byte = data[index] + index += 1 + count |= (byte & ~0x80) << (7 * i) + if (index != 9) and not (byte & 0x80): + break + + log.debug(f"[timestamp] timestamp = {ts}, cycle count = {count}") + + tracer_ts(stream.tracer, ts, data[0] & 1, count, nr_replace) + + return index + + +def decode_exception(data, stream: ETBStream): + index = 0 + EE = 0 + TYPE = 0 + P = 0 + + if data[index] & 1: + # Exception return packet + index += 1 + log.debug("[exception return]") + tracer_exception_return(stream.tracer) + else: + # Exception packet + index += 1 + data1 = data[index] + index += 1 + data2 = 0 + + if data1 & 0x80: # Assuming c_bit is 0x80 + data2 = data[index] + index += 1 + + EE = ((data1 & 0x40) >> 5) | (data1 & 0x01) + TYPE = ((data1 & 0x3E) >> 1) | (data2 & 0x1F) + P = (data2 & 0x20) >> 5 + + log.debug(f"[exception] E1:E0 = {EE}, TYPE = 0x{TYPE:02X}, P = {P}") + + if EE != 1 and EE != 2: + log.error("Invalid EE in the exception packet") + return -1 + elif EE == 2: + # There is an address packet + data1 = data[index] + pkt = stream.decoder.etmv4_pkt_match(data1) + if pkt: + ret = pkt.decode(data[index:], stream) + if ret > 0: + index += ret + else: + log.error("Invalid address packet in the exception packet") + return -1 + else: + log.error("No matching trace packet found for address packet") + return -1 + + tracer_exception(stream.tracer, TYPE) + + return index + + +def decode_cc_format_1(data, stream): + index = 0 + u_bit = data[index] + index += 1 + commit = 0 + count = 0 + + if not stream.tracer.commopt: + for i in range(4): + byte = data[index] + commit |= (byte & ~0x80) << (7 * i) + index += 1 + if not (byte & 0x80): + break + if i >= 4: + log.error( + "More than 4 bytes of the commit section in the cycle count format 1 packet" + ) + return -1 + tracer_commit(stream.tracer, commit) + + if not u_bit: + for i in range(3): + byte = data[index] + count |= (byte & ~0x80) << (7 * i) + index += 1 + if not (byte & 0x80): + break + if i >= 3: + log.error( + "More than 3 bytes of the cycle count section in the cycle count format 1 packet" + ) + return -1 + + log.debug(f"[cycle count format 1] U = {u_bit}, COMMIT = {commit}, COUNT = {count}") + + tracer_cc(stream.tracer, u_bit, count) + return index + + +def decode_cc_format_2(data, stream): + F = data[0] & 0x01 + AAAA = (data[1] & 0xF0) >> 4 + BBBB = data[1] & 0x0F + log.debug(f"[cycle count format 2] F = {F}, AAAA = {AAAA}, BBBB = {BBBB}") + + if F: + commit = stream.tracer.max_spec_depth + AAAA - 15 + else: + commit = AAAA + 1 + if AAAA: + tracer_commit(stream.tracer, commit) + + tracer_cc(stream.tracer, 0, BBBB) + return 2 + + +def decode_cc_format_3(data, stream): + AA = (data[0] & 0x0C) >> 2 + BB = data[0] & 0x03 + log.debug(f"[cycle count format 3] AA = {AA}, BB = {BB}") + + if not stream.tracer.commopt: + tracer_commit(stream.tracer, AA + 1) + + tracer_cc(stream.tracer, 0, BB) + + return 1 + + +def decode_data_sync_marker(data, stream): + if data[0] & 0x08: + log.debug(f"[unnumbered data sync maker] A = {data[0] & 0x07}") + else: + log.debug(f"[numbered data sync maker] NUM = {data[0] & 0x07}") + return 1 + + +def decode_commit(data, stream): + index = 0 + commit = 0 + for i in range(4): + byte = data[index] + commit |= (byte & ~0x80) << (7 * i) + index += 1 + if not (byte & 0x80): + break + + if i >= 4: + log.error("More than 4 bytes of the commit section in the commit packet") + return -1 + log.debug("[commit] COMMIT = %d", commit) + tracer_commit(stream.tracer, commit) + return index + + +def decode_cancel(data, stream: ETBStream): + index = 0 + cancel = 0 + + if not (data[index] & 0x10): + # Cancel format 1 + index += 1 + for i in range(4): + byte = data[index] + cancel |= (byte & ~0x80) << (7 * i) + index += 1 + if not (byte & 0x80): + break + if i >= 4: + log.error( + "More than 4 bytes of the cancel section in the cancel format 1 packet" + ) + return -1 + log.debug(f"[cancel format 1] M = {data[0] & 0x01}, CANCEL = {cancel}") + tracer_cancel(stream.tracer, data[0] & 0x01, cancel) + elif not (data[index] & 0x80): + # Cancel format 2 + index += 1 + log.debug(f"[cancel format 2] A = {data[index] & 0x03}") + action = data[index] & 0x03 + if action == 1: + tracer_atom(stream.tracer, ATOM_TYPE_E) + elif action == 2: + tracer_atom(stream.tracer, ATOM_TYPE_E) + tracer_atom(stream.tracer, ATOM_TYPE_E) + elif action == 3: + tracer_atom(stream.tracer, ATOM_TYPE_N) + else: + log.error("Unexpected A in a cancel format 2 packet") + tracer_cancel(stream.tracer, 1, 1) + else: + # Cancel format 3 + index += 1 + log.debug( + f"[cancel format 3] CC = {(data[index] & 0x06) >> 1}, A = {data[index] & 0x01}" + ) + if data[index] & 0x01: + tracer_atom(stream.tracer, ATOM_TYPE_E) + tracer_cancel(stream.tracer, 1, ((data[index] & 0x06) >> 1) + 2) + + return index + + +def decode_cancel_format_1(data, stream: ETBStream): + return decode_cancel(data, stream) + + +def decode_cancel_format_2(data, stream: ETBStream): + return decode_cancel(data, stream) + + +def decode_cancel_format_3(data, stream: ETBStream): + return decode_cancel(data, stream) + + +def decode_mispredict(data, stream: ETBStream): + log.debug(f"[mispredict] A = {data[0] & 0x03}") + tracer_mispredict(stream.tracer, data[0] & 0x03) + return 1 + + +def decode_cond_inst_format_1(data, stream: ETBStream): + index = 1 + key = 0 + + for i in range(4): + byte = data[index] + key |= (byte & ~0x80) << (7 * i) + index += 1 + if not (byte & 0x80): + break + if i >= 4: + log.error("More than 4 bytes of the commit section in the commit packet") + return -1 + + log.debug(f"[conditional instruction format 1] key = {key}") + + tracer_cond_inst(stream.tracer, 1, key, 0) + + return index + + +def decode_cond_inst_format_2(data, stream: ETBStream): + ci = data[0] & 0x03 + log.debug(f"[conditional instruction format 2] ci = {ci}") + + tracer_cond_inst(stream.tracer, 2, ci, 0) + + return 1 + + +def decode_cond_inst_format_3(data, stream: ETBStream): + z = data[1] & 0x01 + num = (data[1] & 0x7E) >> 1 + log.debug(f"[conditional instruction format 3] z = {z}, num = {num}") + + tracer_cond_inst(stream.tracer, 3, z, num) + + return 2 + + +def decode_cond_flush(data, stream: ETBStream): + log.debug("[conditional flush]") + + tracer_cond_flush(stream.tracer) + + return 1 + + +def decode_cond_result_format_1(data, stream: ETBStream): + index = 0 + nr_payloads = 1 if (data[index] & 0x4) else 2 + index += 1 + + for payload in range(nr_payloads): + CI = (data[0] & 0x1) if payload == 0 else ((data[1] & 0x2) >> 1) + RESULT = data[index] & 0x0F + KEY = (data[index] >> 4) & 0x7 + index += 1 + + for i in range(5): + byte = data[index] + KEY |= (byte & ~0x80) << (7 * i + 3) + index += 1 + if not (byte & 0x80): + break + if i >= 5: + log.error( + "More than 5 payload bytes in the conditional result format 1 packet" + ) + return -1 + + log.debug( + f"[conditional result format 1] CI[{payload}] = {CI}, RESULT[{payload}] = 0x{RESULT:X}, KEY[{payload}] = {KEY}" + ) + + tracer_cond_result(stream.tracer, 1, KEY, CI, RESULT) + + return index + + +def decode_cond_result_format_2(data, stream: ETBStream): + K = (data[0] >> 2) & 0x1 + T = data[0] & 0x3 + log.debug(f"[conditional result format 2] K = {K}, T = 0x{T:X}") + + tracer_cond_result(stream.tracer, 2, K, T, 0) + + return 1 + + +def decode_cond_result_format_3(data, stream: ETBStream): + TOKEN = data[1] | ((data[0] & 0x0F) << 8) + log.debug(f"[conditional result format 3] TOKEN = 0x{TOKEN:X}") + + tracer_cond_result(stream.tracer, 3, TOKEN, 0, 0) + + return 2 + + +def decode_cond_result_format_4(data, stream: ETBStream): + T = data[0] & 0x3 + log.debug(f"[conditional result format 4] T = 0x{T:X}") + + tracer_cond_result(stream.tracer, 4, T, 0, 0) + + return 1 + + +def decode_event(data, stream: ETBStream): + event = data[0] & 0x0F + log.debug(f"[event] EVENT = 0x{event:X}") + return 1 + + +def update_address_regs(stream: ETBStream, address, instruction_set): + stream.tracer.set_address_register(2, stream.tracer.address_register[1].address) + stream.tracer.set_address_register(1, stream.tracer.address_register[0].address) + stream.tracer.set_address_register(0, address) + stream.tracer.set_address_register_IS(0, instruction_set) + + +def decode_short_address(data, stream): + index = 0 + address = stream.tracer.address_register[0].address + instruction_set = ADDR_REG_IS0 if (data[index] & 0x01) else ADDR_REG_IS1 + index += 1 + if instruction_set == ADDR_REG_IS0: + address &= ~0x000001FF + address |= (data[index] & 0x7F) << 2 + index += 1 + if data[index] & 0x80: + address &= ~0x0001FE00 + address |= (data[index] & 0x7F) << 9 + index += 1 + else: + address &= ~0x000000FF + address |= (data[index] & 0x7F) << 1 + index += 1 + if data[1] & 0x80: + address &= ~0x0000FF00 + address |= (data[index]) << 8 + index += 1 + + log.debug( + f"[short address] address = 0x{address:016x}, instruction_set = {instruction_set}" + ) + + update_address_regs(stream, address, instruction_set) + tracer_address(stream.tracer) + return index + + +def decode_short_address_is0(data, stream): + return decode_short_address(data, stream) + + +def decode_short_address_is1(data, stream): + return decode_short_address(data, stream) + + +def decode_long_address(data, stream): + index = 1 + address = stream.tracer.address_register[0].address + + if data[0] == 0x9A: + instruction_set = ADDR_REG_IS0 + address &= ~0xFFFFFFFF + address |= (data[index] & 0x7F) << 2 + address |= (data[index + 1] & 0x7F) << 9 + address |= data[index + 2] << 16 + address |= data[index + 3] << 24 + index += 4 + elif data[0] == 0x9B: + instruction_set = ADDR_REG_IS1 + address &= ~0xFFFFFFFF + address |= (data[index] & 0x7F) << 1 + address |= data[index + 1] << 8 + address |= data[index + 2] << 16 + address |= data[index + 3] << 24 + index += 4 + elif data[0] == 0x9D: + instruction_set = ADDR_REG_IS0 + address = 0 + address |= (data[index] & 0x7F) << 2 + address |= (data[index + 1] & 0x7F) << 9 + address |= data[index + 2] << 16 + address |= data[index + 3] << 24 + address |= data[index + 4] << 32 + address |= data[index + 5] << 40 + address |= data[index + 6] << 48 + address |= data[index + 7] << 56 + index += 8 + elif data[0] == 0x9E: + instruction_set = ADDR_REG_IS1 + address = 0 + address |= (data[index] & 0x7F) << 1 + address |= data[index + 1] << 8 + address |= data[index + 2] << 16 + address |= data[index + 3] << 24 + address |= data[index + 4] << 32 + address |= data[index + 5] << 40 + address |= data[index + 6] << 48 + address |= data[index + 7] << 56 + index += 8 + else: + return -1 + + log.debug( + f"[long address] address = 0x{address:016x}, instruction_set = {instruction_set}" + ) + + update_address_regs(stream, address, instruction_set) + tracer_address(stream.tracer) + + return index + + +def decode_long_address_32bit_is0(data, stream): + return decode_long_address(data, stream) + + +def decode_long_address_32bit_is1(data, stream): + return decode_long_address(data, stream) + + +def decode_long_address_64bit_is0(data, stream): + return decode_long_address(data, stream) + + +def decode_long_address_64bit_is1(data, stream): + return decode_long_address(data, stream) + + +def decode_exact_match_address(data, stream: ETBStream): + QE = data[0] & 0x03 + + address = stream.tracer.address_register[QE].address + instruction_set = stream.tracer.address_register[QE].instruction_set + + log.debug( + f"[Exact match address] QE = {QE}, address = 0x{address:016x}, instruction_set = {instruction_set}" + ) + + update_address_regs(stream, address, instruction_set) + tracer_address(stream.tracer) + + return 1 + + +def decode_context(data, stream): + index = 0 + EL = SF = NS = 0 + V = C = 0 + VMID = 0 + CONTEXTID = 0 + + if data[index] & 1: + index += 1 + EL = data[index] & 0x3 + SF = (data[index] & 0x10) >> 4 + NS = (data[index] & 0x20) >> 5 + if data[index] & 0x40: + V = 1 + index += 1 + VMID = data[index] + if data[index] & 0x80: + C = 1 + index += 1 + CONTEXTID = data[index] + CONTEXTID |= data[index + 1] << 8 + CONTEXTID |= data[index + 2] << 16 + CONTEXTID |= data[index + 3] << 24 + index += 3 + log.debug( + f"[context] P = 1'b1, EL = {EL}, SF = {SF}, NS = {NS}, V = {V}, \n" + f"C = {C}, VMID = {VMID}, CONTEXTID = 0x{CONTEXTID:04X}" + ) + else: + log.debug("[context] P = 1'b0") + + tracer_context(stream.tracer, data[0] & 1, EL, SF, NS, V, VMID, C, CONTEXTID) + + return index + 1 + + +def decode_address_context(data, stream: ETBStream): + index = 1 + address = stream.tracer.address_register[0].address + + if data[0] == 0x82: + instruction_set = ADDR_REG_IS0 + address &= ~0xFFFFFFFF + address |= (data[index] & 0x7F) << 2 + address |= (data[index + 1] & 0x7F) << 9 + address |= data[index + 2] << 16 + address |= data[index + 3] << 24 + index += 4 + elif data[0] == 0x83: + instruction_set = ADDR_REG_IS1 + address &= ~0xFFFFFFFF + address |= (data[index] & 0x7F) << 1 + address |= data[index + 1] << 8 + address |= data[index + 2] << 16 + address |= data[index + 3] << 24 + index += 4 + elif data[0] == 0x85: + instruction_set = ADDR_REG_IS0 + address = 0 + address |= (data[index] & 0x7F) << 2 + address |= (data[index + 1] & 0x7F) << 9 + address |= data[index + 2] << 16 + address |= data[index + 3] << 24 + address |= data[index + 4] << 32 + address |= data[index + 5] << 40 + address |= data[index + 6] << 48 + address |= data[index + 7] << 56 + index += 8 + elif data[0] == 0x86: + instruction_set = ADDR_REG_IS1 + address = 0 + address |= (data[index] & 0x7F) << 1 + address |= data[index + 1] << 8 + address |= data[index + 2] << 16 + address |= data[index + 3] << 24 + address |= data[index + 4] << 32 + address |= data[index + 5] << 40 + address |= data[index + 6] << 48 + address |= data[index + 7] << 56 + index += 8 + else: + return -1 + + update_address_regs(stream, address, instruction_set) + + data_byte = data[index] + EL = data_byte & 0x3 + SF = (data_byte & 0x10) >> 4 + NS = (data_byte & 0x20) >> 5 + V = C = 0 + VMID = 0 + CONTEXTID = 0 + + if data_byte & 0x40: + V = 1 + index += 1 + VMID = data[index] + if data_byte & 0x80: + C = 1 + index += 1 + CONTEXTID = data[index] + CONTEXTID |= data[index + 1] << 8 + CONTEXTID |= data[index + 2] << 16 + CONTEXTID |= data[index + 3] << 24 + index += 3 + + log.debug( + f"[address with context] address = 0x{address:016x}, instruction_set = {instruction_set}, " + f"EL = {EL}, SF = {SF}, NS = {NS}, V = {V}, C = {C}, VMID = {VMID}, CONTEXTID = 0x{CONTEXTID:04X}" + ) + + tracer_context(stream.tracer, 1, EL, SF, NS, V, VMID, C, CONTEXTID) + tracer_address(stream.tracer) + + return index + 1 + + +def decode_address_context_32bit_is0(data, stream): + return decode_address_context(data, stream) + + +def decode_address_context_32bit_is1(data, stream): + return decode_address_context(data, stream) + + +def decode_address_context_64bit_is0(data, stream): + return decode_address_context(data, stream) + + +def decode_address_context_64bit_is1(data, stream): + return decode_address_context(data, stream) + + +def decode_atom_format_1(data, stream): + A = data[0] & 0x01 + log.debug(f"[atom format 1] A = {A}") + tracer_atom(stream.tracer, ATOM_TYPE_E if A != 0 else ATOM_TYPE_N) + return 1 + + +def decode_atom_format_2(data, stream): + A = data[0] & 0x03 + log.debug(f"[atom format 2] A = {A}") + tracer_atom(stream.tracer, ATOM_TYPE_E if A & 1 != 0 else ATOM_TYPE_N) + tracer_atom(stream.tracer, ATOM_TYPE_E if A & 2 != 0 else ATOM_TYPE_N) + return 1 + + +def decode_atom_format_3(data, stream): + A = data[0] & 0x07 + log.debug(f"[atom format 3] A = {A}") + tracer_atom(stream.tracer, ATOM_TYPE_E if A & 1 != 0 else ATOM_TYPE_N) + tracer_atom(stream.tracer, ATOM_TYPE_E if A & 2 != 0 else ATOM_TYPE_N) + tracer_atom(stream.tracer, ATOM_TYPE_E if A & 4 != 0 else ATOM_TYPE_N) + return 1 + + +def decode_atom_format_4(data, stream): + A = data[0] & 0x03 + log.debug(f"[atom format 4] A = {A}") + + if A == 0: + tracer_atom(stream.tracer, ATOM_TYPE_N) + tracer_atom(stream.tracer, ATOM_TYPE_E) + tracer_atom(stream.tracer, ATOM_TYPE_E) + tracer_atom(stream.tracer, ATOM_TYPE_E) + elif A == 1: + tracer_atom(stream.tracer, ATOM_TYPE_N) + tracer_atom(stream.tracer, ATOM_TYPE_N) + tracer_atom(stream.tracer, ATOM_TYPE_N) + tracer_atom(stream.tracer, ATOM_TYPE_N) + elif A == 2: + tracer_atom(stream.tracer, ATOM_TYPE_N) + tracer_atom(stream.tracer, ATOM_TYPE_E) + tracer_atom(stream.tracer, ATOM_TYPE_N) + tracer_atom(stream.tracer, ATOM_TYPE_E) + elif A == 3: + tracer_atom(stream.tracer, ATOM_TYPE_E) + tracer_atom(stream.tracer, ATOM_TYPE_N) + tracer_atom(stream.tracer, ATOM_TYPE_E) + tracer_atom(stream.tracer, ATOM_TYPE_N) + return 1 + + +def decode_atom_format_5_1(data, stream): + ABC = ((data[0] >> 3) & 0x04) | (data[0] & 0x3) + log.debug(f"[atom format 5] ABC = {ABC}") + + if ABC == 5: + tracer_atom(stream.tracer, ATOM_TYPE_N) + tracer_atom(stream.tracer, ATOM_TYPE_E) + tracer_atom(stream.tracer, ATOM_TYPE_E) + tracer_atom(stream.tracer, ATOM_TYPE_E) + tracer_atom(stream.tracer, ATOM_TYPE_E) + elif ABC == 1: + tracer_atom(stream.tracer, ATOM_TYPE_N) + tracer_atom(stream.tracer, ATOM_TYPE_N) + tracer_atom(stream.tracer, ATOM_TYPE_N) + tracer_atom(stream.tracer, ATOM_TYPE_N) + tracer_atom(stream.tracer, ATOM_TYPE_N) + elif ABC == 2: + tracer_atom(stream.tracer, ATOM_TYPE_N) + tracer_atom(stream.tracer, ATOM_TYPE_E) + tracer_atom(stream.tracer, ATOM_TYPE_N) + tracer_atom(stream.tracer, ATOM_TYPE_E) + tracer_atom(stream.tracer, ATOM_TYPE_N) + elif ABC == 3: + tracer_atom(stream.tracer, ATOM_TYPE_E) + tracer_atom(stream.tracer, ATOM_TYPE_N) + tracer_atom(stream.tracer, ATOM_TYPE_E) + tracer_atom(stream.tracer, ATOM_TYPE_N) + tracer_atom(stream.tracer, ATOM_TYPE_E) + else: + log.error("Invalid ABC in an ATOM format 5 packet") + + return 1 + + +def decode_atom_format_5_2(data, stream): + return decode_atom_format_5_1(data, stream) + + +def decode_atom_format_5_3(data, stream): + return decode_atom_format_5_1(data, stream) + + +def decode_atom_format_5_4(data, stream): + return decode_atom_format_5_1(data, stream) + + +def decode_atom_format_6_1(data, stream): + A = (data[0] >> 5) & 0x01 + COUNT = data[0] & 0x1F + if COUNT > 20: + log.error("Invalid COUNT in an ATOM format 6 packet") + return -1 + log.debug(f"[atom format 6] A = {A}, COUNT = {COUNT}") + + for _ in range(COUNT + 3): + tracer_atom(stream.tracer, ATOM_TYPE_E) + tracer_atom(stream.tracer, ATOM_TYPE_N if A else ATOM_TYPE_E) + + return 1 + + +def decode_atom_format_6_2(data, stream): + return decode_atom_format_6_1(data, stream) + + +def decode_atom_format_6_3(data, stream): + return decode_atom_format_6_1(data, stream) + + +def decode_atom_format_6_4(data, stream): + return decode_atom_format_6_1(data, stream) + + +def decode_atom_format_6_5(data, stream): + return decode_atom_format_6_1(data, stream) + + +def decode_atom_format_6_6(data, stream): + return decode_atom_format_6_1(data, stream) + + +def decode_atom_format_6_7(data, stream): + return decode_atom_format_6_1(data, stream) + + +def decode_atom_format_6_8(data, stream): + return decode_atom_format_6_1(data, stream) + + +def decode_atom_format_6_9(data, stream): + return decode_atom_format_6_1(data, stream) + + +def decode_atom_format_6_10(data, stream): + return decode_atom_format_6_1(data, stream) + + +def decode_atom_format_6_11(data, stream): + return decode_atom_format_6_1(data, stream) + + +def decode_atom_format_6_12(data, stream): + return decode_atom_format_6_1(data, stream) + + +def decode_q(data, stream): + index = 0 + type = data[index] & 0x0F + index += 1 + count_unknown = False + address = stream.tracer.address_register[0].address + instruction_set = stream.tracer.address_register[0].instruction_set + + if type in [0, 1, 2]: + address = stream.tracer.address_register[type].address + instruction_set = stream.tracer.address_register[type].instruction_set + update_address_regs(stream, address, instruction_set) + + elif type in [5, 6]: + instruction_set = ADDR_REG_IS0 if type == 5 else ADDR_REG_IS1 + if instruction_set == ADDR_REG_IS0: + address &= ~0x000001FF + address |= (data[index] & 0x7F) << 2 + index += 1 + if data[1] & 0x80: + address &= ~0x0001FE00 + address |= data[index] << 9 + index += 1 + else: + address &= ~0x000000FF + address |= (data[index] & 0x7F) << 1 + index += 1 + if data[1] & 0x80: + address &= ~0x0000FF00 + address |= data[index] << 8 + index += 1 + update_address_regs(stream, address, instruction_set) + + elif type in [10, 11]: + if type == 10: + instruction_set = ADDR_REG_IS0 + address &= ~0xFFFFFFFF + address |= (data[index] & 0x7F) << 2 + address |= (data[index + 1] & 0x7F) << 9 + address |= data[index + 2] << 16 + address |= data[index + 3] << 24 + index += 4 + else: + instruction_set = ADDR_REG_IS1 + address &= ~0xFFFFFFFF + address |= (data[index] & 0x7F) << 1 + address |= data[index + 1] << 8 + address |= data[index + 2] << 16 + address |= data[index + 3] << 24 + index += 4 + update_address_regs(stream, address, instruction_set) + + elif type == 12: + pass + + elif type == 15: + count_unknown = True + + else: + return -1 + + if not count_unknown: + COUNT = 0 + for i in range(5): + byte = data[index] + COUNT |= (byte & ~0x80) << (7 * i + 3) + index += 1 + if not (byte & 0x80): + break + + if count_unknown: + log.debug( + f"[Q] type = {type}, address = 0x{address:016x}, instruction_set = {instruction_set}, count unknown" + ) + else: + log.debug( + f"[Q] type = {type}, address = 0x{address:016x}, instruction_set = {instruction_set}, count = {COUNT}" + ) + + tracer_q(stream.tracer, 0 if count_unknown else COUNT) + tracer_address(stream.tracer) + + return index + + +extension = TracePacket(0xFF, 0x00, decode_extension) +trace_info = TracePacket(0xFF, 0x01, decode_trace_info) +trace_on = TracePacket(0xFF, 0x04, decode_trace_on) +timestamp = TracePacket(0xFE, 0x02, decode_timestamp) +exception = TracePacket(0xFE, 0x06, decode_exception) +cc_format_1 = TracePacket(0xFE, 0x0E, decode_cc_format_1) +cc_format_2 = TracePacket(0xFE, 0x0C, decode_cc_format_2) +cc_format_3 = TracePacket(0xF0, 0x10, decode_cc_format_3) +data_sync_marker = TracePacket(0xF0, 0x20, decode_data_sync_marker) +commit = TracePacket(0xFF, 0x2D, decode_commit) +cancel_format_1 = TracePacket(0xFE, 0x2E, decode_cancel_format_1) +cancel_format_2 = TracePacket(0xFC, 0x34, decode_cancel_format_2) +cancel_format_3 = TracePacket(0xF8, 0x38, decode_cancel_format_3) +mispredict = TracePacket(0xFC, 0x30, decode_mispredict) +cond_inst_format_1 = TracePacket(0xFF, 0x6C, decode_cond_inst_format_1) +cond_inst_format_2 = TracePacket(0xFC, 0x40, decode_cond_inst_format_2) +cond_inst_format_3 = TracePacket(0xFF, 0x6D, decode_cond_inst_format_3) +cond_flush = TracePacket(0xFF, 0x43, decode_cond_flush) +cond_result_format_1 = TracePacket(0xF8, 0x68, decode_cond_result_format_1) +cond_result_format_2 = TracePacket(0xF8, 0x48, decode_cond_result_format_2) +cond_result_format_3 = TracePacket(0xF0, 0x50, decode_cond_result_format_3) +cond_result_format_4 = TracePacket(0xFC, 0x44, decode_cond_result_format_4) +event = TracePacket(0xF0, 0x70, decode_event) +short_address_is0 = TracePacket(0xFF, 0x95, decode_short_address_is0) +short_address_is1 = TracePacket(0xFF, 0x96, decode_short_address_is1) +long_address_32bit_is0 = TracePacket(0xFF, 0x9A, decode_long_address_32bit_is0) +long_address_32bit_is1 = TracePacket(0xFF, 0x9B, decode_long_address_32bit_is1) +long_address_64bit_is0 = TracePacket(0xFF, 0x9D, decode_long_address_64bit_is0) +long_address_64bit_is1 = TracePacket(0xFF, 0x9E, decode_long_address_64bit_is1) +exact_match_address = TracePacket(0xFC, 0x90, decode_exact_match_address) +context = TracePacket(0xFE, 0x80, decode_context) +address_context_32bit_is0 = TracePacket(0xFF, 0x82, decode_address_context_32bit_is0) +address_context_32bit_is1 = TracePacket(0xFF, 0x83, decode_address_context_32bit_is1) +address_context_64bit_is0 = TracePacket(0xFF, 0x85, decode_address_context_64bit_is0) +address_context_64bit_is1 = TracePacket(0xFF, 0x86, decode_address_context_64bit_is1) +atom_format_1 = TracePacket(0xFE, 0xF6, decode_atom_format_1) +atom_format_2 = TracePacket(0xFC, 0xD8, decode_atom_format_2) +atom_format_3 = TracePacket(0xF8, 0xF8, decode_atom_format_3) +atom_format_4 = TracePacket(0xFC, 0xDC, decode_atom_format_4) +atom_format_5_1 = TracePacket(0xFF, 0xF5, decode_atom_format_5_1) +atom_format_5_2 = TracePacket(0xFF, 0xD5, decode_atom_format_5_2) +atom_format_5_3 = TracePacket(0xFF, 0xD6, decode_atom_format_5_3) +atom_format_5_4 = TracePacket(0xFF, 0xD7, decode_atom_format_5_4) +atom_format_6_1 = TracePacket(0xFF, 0xD0, decode_atom_format_6_1) +atom_format_6_2 = TracePacket(0xFF, 0xD1, decode_atom_format_6_2) +atom_format_6_3 = TracePacket(0xFF, 0xD2, decode_atom_format_6_3) +atom_format_6_4 = TracePacket(0xFF, 0xD3, decode_atom_format_6_4) +atom_format_6_5 = TracePacket(0xFF, 0xD4, decode_atom_format_6_5) +atom_format_6_6 = TracePacket(0xFF, 0xF0, decode_atom_format_6_6) +atom_format_6_7 = TracePacket(0xFF, 0xF1, decode_atom_format_6_7) +atom_format_6_8 = TracePacket(0xFF, 0xF2, decode_atom_format_6_8) +atom_format_6_9 = TracePacket(0xFF, 0xF3, decode_atom_format_6_9) +atom_format_6_10 = TracePacket(0xFF, 0xF4, decode_atom_format_6_10) +atom_format_6_11 = TracePacket(0xF0, 0xC0, decode_atom_format_6_11) +atom_format_6_12 = TracePacket(0xF0, 0xE0, decode_atom_format_6_12) +q = TracePacket(0xF0, 0xA0, decode_q) + +# Example usage +etmv4_tracepkts = [ + extension, + trace_info, + trace_on, + timestamp, + exception, + cc_format_1, + cc_format_2, + cc_format_3, + data_sync_marker, + commit, + cancel_format_1, + cancel_format_2, + cancel_format_3, + mispredict, + cond_inst_format_1, + cond_inst_format_2, + cond_inst_format_3, + cond_flush, + cond_result_format_1, + cond_result_format_2, + cond_result_format_3, + cond_result_format_4, + event, + short_address_is0, + short_address_is1, + long_address_32bit_is0, + long_address_32bit_is1, + long_address_64bit_is0, + long_address_64bit_is1, + exact_match_address, + context, + address_context_32bit_is0, + address_context_32bit_is1, + address_context_64bit_is0, + address_context_64bit_is1, + atom_format_1, + atom_format_2, + atom_format_3, + atom_format_4, + atom_format_5_1, + atom_format_5_2, + atom_format_5_3, + atom_format_5_4, + atom_format_6_1, + atom_format_6_2, + atom_format_6_3, + atom_format_6_4, + atom_format_6_5, + atom_format_6_6, + atom_format_6_7, + atom_format_6_8, + atom_format_6_9, + atom_format_6_10, + atom_format_6_11, + atom_format_6_12, + q, +] + + +def etmv4_synchronization(stream: ETBStream): + log.debug(f"MAX_SPEC_DEPTH = {stream.tracer.max_spec_depth}") + log.debug(f"P0_KEY_MAX = {stream.tracer.p0_key_max}") + log.debug(f"COND_KEY_MAX_INCR = {stream.tracer.cond_key_max_incr}") + log.debug(f"CONDTYPE = {stream.tracer.condtype}") + log.debug(f"COMMOPT = {stream.tracer.commopt}") + PKT_SIZE = 12 + + # Locate an async packet and search for a trace-info packet + for i in range(len(stream.buff)): + c = stream.buff[i] + if (c & extension.mask) == extension.val: + p = extension.decode(stream.buff[i:], stream) + if p != PKT_SIZE: + continue + c = stream.buff[i + PKT_SIZE] + if (c & trace_info.mask) == trace_info.val: + p = trace_info.decode(stream.buff[i + PKT_SIZE :], stream) + if p > 0: + # SYNCING -> INSYNC + stream.state = StreamState.INSYNC + stream.tracer.reset_address_register() + return i + + log.error("No trace info packet right after an a-sync packet") + + return -1 + + +class ETMv4Decoder: + def __init__(self): + self.pkt_map = {} + + for c in range(256): + for pkt in etmv4_tracepkts: + if (c & pkt.mask) == pkt.val: + self.pkt_map[c] = pkt + break + + def etmv4_pkt_match(self, c): + return self.pkt_map.get(c, None) + + def synchronization(self, stream: ETBStream): + return etmv4_synchronization(stream) + + +def decode_stream(stream: ETBStream): + if stream.state != StreamState.READING: + log.error("Stream state is not correct") + return -1 + + stream.state = StreamState.SYNCING + log.debug("Syncing the trace stream...") + cur = stream.decoder.synchronization(stream) + if cur < 0: + log.error("Cannot find any synchronization packet") + return -1 + else: + log.debug(f"Trace starts from offset {cur}") + + stream.state = StreamState.DECODING + + log.debug("Decoding the trace stream...") + buff_mv = memoryview(stream.buff) + total_len = len(buff_mv) + + while cur < total_len: + c = buff_mv[cur] + pkt = stream.decoder.etmv4_pkt_match(c) + if pkt: + log.debug(f"Get a packet of type {pkt.name}") + else: + log.error(f"Cannot recognize a packet header 0x{c:02x}, offset: {cur}") + log.error(f"Proceed on guesswork, offset: {cur}") + cur += 1 + continue + + ret = pkt.decode(buff_mv[cur:], stream) + + if ret <= 0: + log.error(f"Proceed on guesswork, offset: {cur}") + cur += 1 + else: + cur += ret + + log.debug("Complete decode of the trace stream") + return 0 + + +def decode_etb(stream: ETBStream, unaligned: bool): + FSYNC = bytes([0xFF, 0xFF, 0xFF, 0x7F]) + ETB_PACKET_SIZE = 16 + NULL_TRACE_SOURCE = 0 + + pkt_idx = 0 + cur_id = -1 + pre_id = -1 + nr_stream = 1 + streams = [stream.copy() for _ in range(nr_stream)] + buff_mv = stream.buff + total_len = len(buff_mv) + + pkt_idx = buff_mv.find(FSYNC) if unaligned else 0 + if pkt_idx == -1: + log.error("No frame synchronization packet found.") + return -1 + + for s in streams: + if not isinstance(s.buff, bytearray): + s.buff = bytearray(s.buff) + + while pkt_idx + ETB_PACKET_SIZE <= total_len: + sync_ofs = buff_mv[pkt_idx : pkt_idx + 4] == FSYNC + if sync_ofs: + pkt_idx += 4 + + if pkt_idx + ETB_PACKET_SIZE >= total_len: + break + + end = buff_mv[pkt_idx + ETB_PACKET_SIZE - 1] + + byte_idx = 0 + log.debug(f"ofs: {pkt_idx}, cur_id: {cur_id}") + while byte_idx < ETB_PACKET_SIZE - 1: + c = buff_mv[pkt_idx + byte_idx] + + if (byte_idx & 1) == 0: + if c & 1: + id = (c >> 1) & 0x7F + if id == NULL_TRACE_SOURCE: + log.info("Found a NULL_TRACE_SOURCE ID in the ETB data packet") + break + pre_id = cur_id + cur_id = id - 1 + if cur_id >= len(streams): + streams.extend( + stream.copy() for _ in range(cur_id - len(streams) + 1) + ) + else: + c |= (end & (1 << (byte_idx // 2))) and 1 + if cur_id >= 0: + log.debug( + f"==Got a data byte {c:02x} at offset {len(streams[cur_id].buff)}, pkt_idx: {pkt_idx}" + ) + streams[cur_id].buff.append(c) + else: + tmp = buff_mv[pkt_idx + byte_idx - 1] + if (tmp & 1) and (end & (1 << (byte_idx // 2))): + if pre_id >= 0: + log.debug( + f"==Got a data byte {c:02x} at offset {len(streams[cur_id].buff)}, pkt_idx: {pkt_idx}" + ) + streams[pre_id].buff.append(c) + else: + if cur_id >= 0: + log.debug( + f"==Got a data byte {c:02x} at offset {len(streams[cur_id].buff)}, pkt_idx: {pkt_idx}" + ) + streams[cur_id].buff.append(c) + + byte_idx += 1 + + pkt_idx += ETB_PACKET_SIZE + + cnt = 0 + for i, s in enumerate(streams): + log.debug(f"There are {len(s.buff)} bytes in the stream {i}") + if len(s.buff) != 0: + log.info(f"Decode trace stream of ID {i}") + decode_stream(s) + cnt += 1 + else: + log.info(f"There is no valid data in the stream of ID {i}") + + print(f"Decode {cnt} streams") + return 0 diff --git a/tools/pynuttx/nxtrace/perfetto_trace.py b/tools/pynuttx/nxtrace/perfetto_trace.py index db299afe388..11e302ed763 100644 --- a/tools/pynuttx/nxtrace/perfetto_trace.py +++ b/tools/pynuttx/nxtrace/perfetto_trace.py @@ -28,6 +28,7 @@ except ImportError: print("pip install protobuf==4.25.3") exit(1) +from . import PerfettoTraceBadArgsError from . import perfetto_trace_pb2 as pb2 logger = logging.getLogger(__name__) @@ -113,6 +114,13 @@ class TraceInstanceFactory: class PerfettoTrace: + DEFAULT_TRUSTED_PACKET_SEQUENCE_ID = 0 + + SLICE_BEGIN = pb2.TrackEvent.Type.TYPE_SLICE_BEGIN + SLICE_END = pb2.TrackEvent.Type.TYPE_SLICE_END + INSTANT = pb2.TrackEvent.Type.TYPE_INSTANT + COUNTER = pb2.TrackEvent.Type.TYPE_COUNTER + def __init__(self, filename: str): """Create a trace""" self.flush_threshold = 10000 @@ -120,6 +128,39 @@ class PerfettoTrace: self.trace = pb2.Trace() self.file = open(filename, "wb") + self.current_uuid = 0 + + def fill_debug_annotation_value(self, debug_annotation, value): + if isinstance(value, dict): + for key in value: + dict_entry = pb2.DebugAnnotation() + dict_entry.name = key + self.fill_debug_annotation_value(dict_entry, value[key]) + debug_annotation.dict_entries.append(dict_entry) + elif isinstance(value, list): + for item in value: + array_value = pb2.DebugAnnotation() + self.fill_debug_annotation_value(array_value, item) + debug_annotation.array_values.append(array_value) + elif isinstance(value, bool): + debug_annotation.bool_value = value + elif isinstance(value, int): + debug_annotation.int_value = value + elif isinstance(value, float): + debug_annotation.double_value = value + elif isinstance(value, str): + debug_annotation.string_value = value + elif value is None: + debug_annotation.string_value = "None" + else: + raise PerfettoTraceBadArgsError( + f"cannot convert value {value} of type {type(value)} to DebugAnnotation value" + ) + + def next_uuid(self): + self.current_uuid += 1 + return self.current_uuid + def init(self): # Initialize clock snapshots clocks_class = TraceClassFactory("ClockSnapshot.Clock") @@ -294,3 +335,55 @@ class PerfettoTrace: def atrace_int(self, head: TraceHead, msg, value): return self.print(head, f"C|{head.pid}|{msg}|{value}") + + def add_process(self, uuid, pid, name): + self.trace.packet.append( + pb2.TracePacket( + track_descriptor=pb2.TrackDescriptor( + uuid=uuid, process=pb2.ProcessDescriptor(pid=pid, process_name=name) + ), + trusted_packet_sequence_id=self.DEFAULT_TRUSTED_PACKET_SEQUENCE_ID, + ) + ) + + def add_thread(self, uuid, parent_uuid, tid, pid, name): + self.trace.packet.append( + pb2.TracePacket( + track_descriptor=pb2.TrackDescriptor( + uuid=uuid, + parent_uuid=parent_uuid, + thread=pb2.ThreadDescriptor(pid=pid, tid=tid, thread_name=name), + ), + trusted_packet_sequence_id=self.DEFAULT_TRUSTED_PACKET_SEQUENCE_ID, + ) + ) + + def trace_event(self, uuid, ts, type, name=None, flow_ids=[], args={}): + pkt = self.trace.packet.add() + pkt.timestamp = ts + pkt.track_event.type = type + pkt.track_event.track_uuid = uuid + pkt.trusted_packet_sequence_id = self.DEFAULT_TRUSTED_PACKET_SEQUENCE_ID + + if args: + if not isinstance(args, dict): + raise PerfettoTraceBadArgsError("slice args is not dict") + annotations = [] + + for key in args: + debug_annotation = pb2.DebugAnnotation() + debug_annotation.name = key + self.fill_debug_annotation_value(debug_annotation, args[key]) + + annotations.append(debug_annotation) + + pkt.track_event.debug_annotations.extend(annotations) + + if name: + pkt.track_event.name = name + if flow_ids: + pkt.track_event.flow_ids = flow_ids + + def trace_slice(self, uuid, start, end, name, flow_ids=[], args={}): + self.trace_event(uuid, start, self.SLICE_BEGIN, name, flow_ids, args) + self.trace_event(uuid, end, self.SLICE_END) diff --git a/tools/pynuttx/requirements.txt b/tools/pynuttx/requirements.txt index 77d779c645e..ec6fb47f086 100644 --- a/tools/pynuttx/requirements.txt +++ b/tools/pynuttx/requirements.txt @@ -1,3 +1,5 @@ +angr +capstone construct debugpy lief -- Gitee From 82da6e267f703b8a459eecdfb85b131478008e4d Mon Sep 17 00:00:00 2001 From: ganjing Date: Thu, 20 Mar 2025 16:04:11 +0800 Subject: [PATCH 143/235] fix: continue running even if the ps command reports an error VELAPLATFO-56660 Change-Id: I6309ae23bb6b3b70b334d5cfd67998e789a098c8 Signed-off-by: ganjing --- tools/pynuttx/nxgdb/thread.py | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/tools/pynuttx/nxgdb/thread.py b/tools/pynuttx/nxgdb/thread.py index 27a68438a20..a890eb1f540 100644 --- a/tools/pynuttx/nxgdb/thread.py +++ b/tools/pynuttx/nxgdb/thread.py @@ -560,4 +560,9 @@ class Ps(gdb.Command): gdb.write("\n") for tcb in utils.get_tcbs(): - self.parse_and_show_info(tcb) + try: + self.parse_and_show_info(tcb) + except gdb.error as e: + gdb.write(f"[Error] GDB error while processing TCB: {e}\n") + except Exception as e: + gdb.write(f"[Error] Unexpected error: {e}\n") -- Gitee From 4258b8f33f57e978895ebab5ce6e087d2d7b89ef Mon Sep 17 00:00:00 2001 From: wangmingrong1 Date: Thu, 20 Mar 2025 17:05:40 +0800 Subject: [PATCH 144/235] gdb diagnose: Support report backtrace VELAPLATFO-56659 Change-Id: Idf13aac9b9f84cc7bfa6bf2f6f7d671e9e28b6c2 Signed-off-by: wangmingrong1 --- tools/pynuttx/nxgdb/nxcrash/busyloop.py | 1 + tools/pynuttx/nxgdb/nxcrash/stackoverflow.py | 7 ++++++- tools/pynuttx/nxgdb/nxcrash/thread.py | 7 ++++++- tools/pynuttx/nxgdb/utils.py | 6 ++++++ 4 files changed, 19 insertions(+), 2 deletions(-) diff --git a/tools/pynuttx/nxgdb/nxcrash/busyloop.py b/tools/pynuttx/nxgdb/nxcrash/busyloop.py index bf4ccd6feaf..aa0e217cb9f 100644 --- a/tools/pynuttx/nxgdb/nxcrash/busyloop.py +++ b/tools/pynuttx/nxgdb/nxcrash/busyloop.py @@ -71,6 +71,7 @@ class CrashBusyloop(gdb.Command): "pid": tcb["pid"], "name": utils.get_task_name(tcb), "cpuload": cpuload, + "backtrace": utils.Backtrace(utils.get_backtrace(int(tcb["pid"]))), } for tcb, cpuload in collected ], diff --git a/tools/pynuttx/nxgdb/nxcrash/stackoverflow.py b/tools/pynuttx/nxgdb/nxcrash/stackoverflow.py index 1b9c446ea99..eca0a945e1f 100644 --- a/tools/pynuttx/nxgdb/nxcrash/stackoverflow.py +++ b/tools/pynuttx/nxgdb/nxcrash/stackoverflow.py @@ -73,7 +73,12 @@ class CrashStackOverflow(gdb.Command): "result": "fail" if collected else "pass", "command": "crash stackoverflow", "thread": [ - {"pid": tcb["pid"], "name": utils.get_task_name(tcb), "filled": filled} + { + "pid": tcb["pid"], + "name": utils.get_task_name(tcb), + "filled": filled, + "backtrace": utils.Backtrace(utils.get_backtrace(int(tcb["pid"]))), + } for tcb, filled in collected ], } diff --git a/tools/pynuttx/nxgdb/nxcrash/thread.py b/tools/pynuttx/nxgdb/nxcrash/thread.py index 490493ba771..b754c82d864 100644 --- a/tools/pynuttx/nxgdb/nxcrash/thread.py +++ b/tools/pynuttx/nxgdb/nxcrash/thread.py @@ -63,6 +63,11 @@ class CrashThread(gdb.Command): "result": "fail" if tcbs else "pass", "command": "crash thread", "thread": [ - {"pid": tcb["pid"], "name": utils.get_task_name(tcb)} for tcb in tcbs + { + "pid": tcb["pid"], + "name": utils.get_task_name(tcb), + "backtrace": utils.Backtrace(utils.get_backtrace(int(tcb["pid"]))), + } + for tcb in tcbs ], } diff --git a/tools/pynuttx/nxgdb/utils.py b/tools/pynuttx/nxgdb/utils.py index c106b63f9dc..1e48103957c 100644 --- a/tools/pynuttx/nxgdb/utils.py +++ b/tools/pynuttx/nxgdb/utils.py @@ -226,6 +226,12 @@ class Backtrace: def __getitem__(self, index): return self.backtrace.__getitem__(index) + def toJSON(self): + return [ + {"address": addr, "function": func, "source": source} + for addr, func, source in self.backtrace + ] + def lookup_type(name, block=None) -> gdb.Type: """Return the type object of a type name""" -- Gitee From adb46fd7632641be8b4e108f0424f5a6772eaff8 Mon Sep 17 00:00:00 2001 From: wangmingrong1 Date: Mon, 24 Mar 2025 11:53:48 +0800 Subject: [PATCH 145/235] gdb diagnose: crash thread return running thread when no obvious crash VELAPLATFO-56659 Change-Id: I00bf6eb99fec43e1ea139f56069fe96b56da3361 Signed-off-by: wangmingrong1 --- tools/pynuttx/nxgdb/nxcrash/thread.py | 2 +- tools/pynuttx/nxgdb/utils.py | 6 ++++++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/tools/pynuttx/nxgdb/nxcrash/thread.py b/tools/pynuttx/nxgdb/nxcrash/thread.py index b754c82d864..4e7a1fcde5f 100644 --- a/tools/pynuttx/nxgdb/nxcrash/thread.py +++ b/tools/pynuttx/nxgdb/nxcrash/thread.py @@ -42,7 +42,7 @@ class CrashThread(gdb.Command): collected.append(tcb) break - return collected + return collected or utils.get_running_tcbs() def invoke(self, arg: str, from_tty: bool) -> None: collected = self.collect(utils.get_tcbs()) diff --git a/tools/pynuttx/nxgdb/utils.py b/tools/pynuttx/nxgdb/utils.py index 1e48103957c..58eb8ab3d57 100644 --- a/tools/pynuttx/nxgdb/utils.py +++ b/tools/pynuttx/nxgdb/utils.py @@ -845,6 +845,12 @@ def get_tcb(pid) -> Tcb: return tcb +def get_running_tcbs() -> List[Tcb]: + """get running tcbs""" + running_tasks = parse_and_eval("g_running_tasks") + return [tcb for tcb in ArrayIterator(running_tasks) if tcb] + + def get_tcb_type(tcb): """get tcb type""" if not tcb: -- Gitee From 5eb98689cf2b5f1de5a8597fc2d6bdabe6a9a81f Mon Sep 17 00:00:00 2001 From: guohao15 Date: Tue, 18 Feb 2025 06:32:55 +0000 Subject: [PATCH 146/235] pynuttx: mm Add memory range function VELAPLATFO-56718 Change-Id: Ida84b087ef76d5d0cc46dc72e0660c9a13fc8e41 Signed-off-by: yinshengkai --- tools/pynuttx/nxgdb/mm.py | 35 +++++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) diff --git a/tools/pynuttx/nxgdb/mm.py b/tools/pynuttx/nxgdb/mm.py index a26bbe33876..a35f00f55a3 100644 --- a/tools/pynuttx/nxgdb/mm.py +++ b/tools/pynuttx/nxgdb/mm.py @@ -632,6 +632,41 @@ def get_pools(heaps: List[Value] = []) -> Generator[MemPool, None, None]: yield pool +def memory_range(): + # Execute the GDB command to get section info + section = gdb.execute("maintenance info sections", to_string=True) + memranges = [] + + # Parse the output to find sections with ALLOC and LOAD + for line in section.splitlines(): + if "ALLOC" in line and "READONLY" not in line: + parts = line.split() + start = int(parts[1].split("->")[0], 16) + end = int(parts[1].split("->")[1], 16) + memranges.append((start, end)) + + # Get heaps from memdump + for heap in get_heaps(): + for i in range(heap.nregions): + start = int(heap["mm_heapstart"][i]) + end = int(heap["mm_heapend"][i]) + + for r in memranges: + # If the address range is already in memranges, skip + if r[0] <= start and r[1] >= end: + break + # If the new address range includes a range in memranges, + # delete the old one and add the new one + elif start <= r[0] and end >= r[1]: + memranges.remove(r) + memranges.append((start, end)) + break + else: + memranges.append((start, end)) + + return memranges + + class MMHeapInfo(gdb.Command): """Show basic heap information""" -- Gitee From c59cbb30386e6bdb78c1ed0e75326397cd2dcb9a Mon Sep 17 00:00:00 2001 From: yinshengkai Date: Fri, 21 Mar 2025 11:10:09 +0800 Subject: [PATCH 147/235] pynuttx/gcore: Set the default objcopy prefix VELAPLATFO-56718 Change-Id: I2b3630f22bd994ed9f06885459c6ceab420c0d06 Signed-off-by: yinshengkai --- tools/pynuttx/nxgdb/gcore.py | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/tools/pynuttx/nxgdb/gcore.py b/tools/pynuttx/nxgdb/gcore.py index 8a2deabfaee..49a853cb54b 100644 --- a/tools/pynuttx/nxgdb/gcore.py +++ b/tools/pynuttx/nxgdb/gcore.py @@ -38,9 +38,10 @@ def parse_args(args): parser = argparse.ArgumentParser() parser.add_argument("-o", "--output", help="Gcore output file") parser.add_argument( - "-t", - "--objcopy", - help="Select the appropriate architecture for the objcopy tool", + "-p", + "--prefix", + help="Prefix for objcopy tool", + default="", type=str, ) @@ -132,12 +133,13 @@ class NXGcore(gdb.Command): create_file_with_size(section, end - start) + gdb.write(f"Using objcopy: {args.prefix}objcopy") os.system( - f"{args.objcopy} --add-section {section}={section} " + f"{args.prefix}objcopy --add-section {section}={section} " f"--set-section-flags {section}=noload,alloc {tmpfile.name}" ) os.system( - f"{args.objcopy} --change-section-address " + f"{args.prefix}objcopy --change-section-address " f"{section}={hex(start)} {tmpfile.name}" ) -- Gitee From 008f766e591c54e6ac0e85c11602637303f5296b Mon Sep 17 00:00:00 2001 From: yinshengkai Date: Fri, 21 Mar 2025 11:47:45 +0800 Subject: [PATCH 148/235] pynuttx/gcore: get the default memory range from elf section VELAPLATFO-56718 Change-Id: Iba0c285b5acd2d15c2c4011e3754dbd9831661c9 Signed-off-by: yinshengkai --- tools/pynuttx/nxgdb/gcore.py | 21 ++++++++------------- 1 file changed, 8 insertions(+), 13 deletions(-) diff --git a/tools/pynuttx/nxgdb/gcore.py b/tools/pynuttx/nxgdb/gcore.py index 49a853cb54b..6acdd0ac41b 100644 --- a/tools/pynuttx/nxgdb/gcore.py +++ b/tools/pynuttx/nxgdb/gcore.py @@ -26,7 +26,7 @@ import shutil import gdb -from . import utils +from . import mm, utils def create_file_with_size(filename, size): @@ -100,23 +100,18 @@ class NXGcore(gdb.Command): else: corefile = elffile + ".core" - # Obtain memory range from macros or parameters - + # Get memory range from parameter or elf if args.memrange: memregion = args.memrange else: - memregion = str(utils.get_symbol_value("CONFIG_BOARD_MEMORY_RANGE")) - if len(memregion) < 3: - print( - "Please set CONFIG_BOARD_MEMORY_RANGE.\n" - "Memory range of board. format: ,,,....\n" - "start: start address of memory range\n" - "end: end address of memory range\n" - "flags: Readable 0x1, writable 0x2, executable 0x4\n" - "example:0x1000,0x2000,0x1,0x2000,0x3000,0x3,0x3000,0x4000,0x7" - ) + memranges = mm.memory_range() + if not memranges: + gdb.write("ERROR: No loadable sections found.\n") return + memregion = ",".join(f"{start:#x},{end:#x},0x7" for start, end in memranges) + gdb.write(f"Memory ranges: {memregion}\n") + # Resolve memory range and shell run commands values = memregion.replace('"', "").split(",") -- Gitee From ff3e4acdaffe3dc0a86f571e6dbec5bdfe0228ce Mon Sep 17 00:00:00 2001 From: xuxingliang Date: Wed, 26 Mar 2025 12:04:24 +0800 Subject: [PATCH 149/235] nxgdb: fix sim nxthread won't work VELAPLATFO-57076 On sim platform, only limited number of regsiters are stored in TCB context, different than architecture x86-64. This is fixed by looking up g_reginfo in elf, and only touch found registers in GDB. Change-Id: I9684f44bf8d485f93644a3c936fb7dec80e21b1a Signed-off-by: xuxingliang --- tools/pynuttx/nxreg/register.py | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/tools/pynuttx/nxreg/register.py b/tools/pynuttx/nxreg/register.py index 835ae739c98..b05438f224e 100644 --- a/tools/pynuttx/nxreg/register.py +++ b/tools/pynuttx/nxreg/register.py @@ -173,7 +173,7 @@ g_reg_table = { ("rsi", 4, REGINFO_OFFSET_AUTO), ("rdi", 5, REGINFO_OFFSET_AUTO), ("rbp", 6, REGINFO_OFFSET_AUTO), - ("fsp", 7, REGINFO_OFFSET_AUTO), + ("rsp", 7, REGINFO_OFFSET_AUTO), ("r8", 8, REGINFO_OFFSET_AUTO), ("r9", 9, REGINFO_OFFSET_AUTO), ("r10", 10, REGINFO_OFFSET_AUTO), @@ -183,7 +183,7 @@ g_reg_table = { ("r14", 14, REGINFO_OFFSET_AUTO), ("r15", 15, REGINFO_OFFSET_AUTO), ("rip", 16, REGINFO_OFFSET_AUTO), - ("rflags", 17, REGINFO_OFFSET_AUTO), + ("eflags", 17, REGINFO_OFFSET_AUTO), ("cs", 18, REGINFO_OFFSET_AUTO), ("ss", 19, REGINFO_OFFSET_AUTO), ("ds", 20, REGINFO_OFFSET_AUTO), @@ -386,14 +386,18 @@ class GeneralRegisters: reginfo = get_reginfo(elf) layouts = g_reg_table.get(self.arch, {}).get("registers", []) - regoffsets = [r.tcb_offset for r in reginfo if r.tcb_offset != UINT16_MAX] for i, (name, regnum, offset, *fixed) in enumerate(layouts): + info = next((r for r in reginfo if r.name == name), None) + if not info or info.tcb_offset == UINT16_MAX: + self.logger.debug(f"Register {name}({regnum}) not found in TCB") + continue + register = Register( name=name, regnum=regnum, size=regsize, offset=offset, - tcb_reg_off=regoffsets[i] if i < len(regoffsets) else 0, + tcb_reg_off=info.tcb_offset, fixedvalue=fixed[0] if fixed else None, ) -- Gitee From d3c7df8713eca6ceed3256c35daada98bfd0bfa4 Mon Sep 17 00:00:00 2001 From: xuxingliang Date: Wed, 26 Mar 2025 12:22:51 +0800 Subject: [PATCH 150/235] nxgdb: add maint reginfo command for debug purpose VELAPLATFO-57076 Make it easier to debug register issues. (gdb) maint reginfo Name: the register name GDB uses. Rmt Nr: the register number in RSP packet, also the position in tcb.xcp.regs Tcb Reg Off: the byte offset in tcb.xcp.regs Name Rmt Nr Offset Tcb Reg Off rbx 1 0 0 rbp 6 0 16 rsp 7 0 8 r12 12 0 24 r13 13 0 32 r14 14 0 40 r15 15 0 48 rip 16 0 56 (gdb) Change-Id: Ia7ef6db657cd6733e2df15a2bbe3725f30c3e3f1 Signed-off-by: xuxingliang --- tools/pynuttx/nxgdb/thread.py | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/tools/pynuttx/nxgdb/thread.py b/tools/pynuttx/nxgdb/thread.py index a890eb1f540..a084b5918e8 100644 --- a/tools/pynuttx/nxgdb/thread.py +++ b/tools/pynuttx/nxgdb/thread.py @@ -114,6 +114,33 @@ class NxRegisters: g_registers = NxRegisters() +class RegInfoCommand(gdb.Command): + """Display the register information""" + + def __init__(self): + super().__init__("maintenance reginfo", gdb.COMMAND_USER) + + def invoke(self, arg: str, from_tty: bool) -> None: + registers = g_registers.registers + header = ("Name", "Rmt Nr", "Offset", "Tcb Reg Off") + print( + "Name: the register name GDB uses.\n" + "Rmt Nr: the register number in RSP packet, also the position in tcb.xcp.regs \n" + "Tcb Reg Off: the byte offset in tcb.xcp.regs" + ) + formatter = "{:<20} {:<10} {:<10} {:<10}" + print(formatter.format(*header)) + for register in registers: + print( + formatter.format( + register.name, + register.regnum, + register.offset, + register.tcb_reg_off, + ) + ) + + class SetRegs(gdb.Command): """Load registers from TCB context memory address. Usage: setregs [regs] -- Gitee From addcd5a409820fb5203dbe240c2f5d6e4b9b983b Mon Sep 17 00:00:00 2001 From: xuxingliang Date: Thu, 27 Mar 2025 12:15:02 +0800 Subject: [PATCH 151/235] nxgdb/thread: make sure gdb.execute output to stdout VELAPLATFO-56718 When use pipe mycommand | tee output.log, the output of gdb.execute won't be redirected. This patch fixes it Change-Id: I921e3201745acd20d0005f186c7c664ddd9d3b67 Signed-off-by: xuxingliang --- tools/pynuttx/nxgdb/thread.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tools/pynuttx/nxgdb/thread.py b/tools/pynuttx/nxgdb/thread.py index a084b5918e8..16f56c26d8d 100644 --- a/tools/pynuttx/nxgdb/thread.py +++ b/tools/pynuttx/nxgdb/thread.py @@ -312,7 +312,7 @@ class Nxthread(gdb.Command): for cmd in arg[2:]: cmd_arg += cmd + " " - gdb.execute(f"{cmd_arg}\n") + gdb.write(gdb.execute(f"{cmd_arg}\n", to_string=True)) g_registers.restore() else: threadlist = [] @@ -340,7 +340,7 @@ class Nxthread(gdb.Command): gdb.write(f"Thread {i}\n") gdb.execute(f"setregs g_pidhash[{i}]->xcp.regs") - gdb.execute(f"{cmd}\n") + gdb.write(gdb.execute(f"{cmd}\n", to_string=True)) g_registers.restore() else: -- Gitee From f18eefa71090172e9efbab3d59f7b4d758298177 Mon Sep 17 00:00:00 2001 From: xuxingliang Date: Wed, 26 Mar 2025 20:46:45 +0800 Subject: [PATCH 152/235] nxgdb/mm: add function to parse memory range argument VELAPLATFO-56718 Use specified argument or parse from ELF and heap. Add option to include heap memory or ELF globals variables Change-Id: Idcb450203ab10d6f41848823a853fe1f611de83c Signed-off-by: xuxingliang --- tools/pynuttx/nxgdb/gcore.py | 20 +-------- tools/pynuttx/nxgdb/mm.py | 80 ++++++++++++++++++++++++------------ 2 files changed, 55 insertions(+), 45 deletions(-) diff --git a/tools/pynuttx/nxgdb/gcore.py b/tools/pynuttx/nxgdb/gcore.py index 6acdd0ac41b..3d68fb85187 100644 --- a/tools/pynuttx/nxgdb/gcore.py +++ b/tools/pynuttx/nxgdb/gcore.py @@ -101,25 +101,9 @@ class NXGcore(gdb.Command): corefile = elffile + ".core" # Get memory range from parameter or elf - if args.memrange: - memregion = args.memrange - else: - memranges = mm.memory_range() - if not memranges: - gdb.write("ERROR: No loadable sections found.\n") - return - - memregion = ",".join(f"{start:#x},{end:#x},0x7" for start, end in memranges) - gdb.write(f"Memory ranges: {memregion}\n") - - # Resolve memory range and shell run commands - - values = memregion.replace('"', "").split(",") - - for i in range(0, len(values), 3): - start = int(values[i], 16) - end = int(values[i + 1], 16) + memrange = mm.get_memrange(args.memrange) + for i, (start, end) in enumerate(memrange): # Create a random section name section = tmpfile.name + f"{i // 3}" diff --git a/tools/pynuttx/nxgdb/mm.py b/tools/pynuttx/nxgdb/mm.py index a35f00f55a3..1dfa6e3fc66 100644 --- a/tools/pynuttx/nxgdb/mm.py +++ b/tools/pynuttx/nxgdb/mm.py @@ -572,7 +572,7 @@ class MMHeap(Value, p.MMHeap): return utils.get_field(self, "mm_mpool", default=None) @property - def regions(self): + def regions(self) -> List[Tuple[MMNode, MMNode]]: if not self._regions: regions = self.nregions self._regions = [] @@ -632,39 +632,65 @@ def get_pools(heaps: List[Value] = []) -> Generator[MemPool, None, None]: yield pool -def memory_range(): +def memory_range(heap=True, globals=True) -> List[Tuple[int, int]]: # Execute the GDB command to get section info - section = gdb.execute("maintenance info sections", to_string=True) memranges = [] + if globals: + section = gdb.execute("maintenance info sections", to_string=True) + + # Parse the output to find sections with ALLOC and LOAD + for line in section.splitlines(): + if "ALLOC" in line and "READONLY" not in line: + parts = line.split() + start = int(parts[1].split("->")[0], 16) + end = int(parts[1].split("->")[1], 16) + if start == end: + continue - # Parse the output to find sections with ALLOC and LOAD - for line in section.splitlines(): - if "ALLOC" in line and "READONLY" not in line: - parts = line.split() - start = int(parts[1].split("->")[0], 16) - end = int(parts[1].split("->")[1], 16) - memranges.append((start, end)) + memranges.append((start, end)) # Get heaps from memdump - for heap in get_heaps(): - for i in range(heap.nregions): - start = int(heap["mm_heapstart"][i]) - end = int(heap["mm_heapend"][i]) - - for r in memranges: - # If the address range is already in memranges, skip - if r[0] <= start and r[1] >= end: - break - # If the new address range includes a range in memranges, - # delete the old one and add the new one - elif start <= r[0] and end >= r[1]: - memranges.remove(r) + if heap: + for heap in get_heaps(): + for i in range(heap.nregions): + start = int(heap["mm_heapstart"][i]) + end = int(heap["mm_heapend"][i]) + + if start == end: + continue + + for r in memranges: + # If the address range is already in memranges, skip + if r[0] <= start and r[1] >= end: + break + # If the new address range includes a range in memranges, + # delete the old one and add the new one + elif start <= r[0] and end >= r[1]: + memranges.remove(r) + memranges.append((start, end)) + break + else: memranges.append((start, end)) - break - else: - memranges.append((start, end)) + return sorted(memranges, key=lambda x: x[0]) - return memranges + +def get_memrange( + rangestr: str = "", heap_only=False, globals_only=False +) -> List[Tuple[int, int]]: + """ + Parse memory range from string or get from heap and globals, + the string should be in the format of "start1,end1,attr1 start2,end2,attr2". + """ + if rangestr: + values = rangestr.replace('"', "").split(",") + memrange = [] + for i in range(0, len(values), 3): + start = utils.parse_arg(values[i]) + end = utils.parse_arg(values[i + 1]) + memrange.append((start, end)) + return memrange + else: + return memory_range(heap=not globals_only, globals=not heap_only) class MMHeapInfo(gdb.Command): -- Gitee From 54fe45a196b187790d32825147668b16c87f2aeb Mon Sep 17 00:00:00 2001 From: xuxingliang Date: Wed, 26 Mar 2025 17:42:57 +0800 Subject: [PATCH 153/235] nxgdb: add dump ram command VELAPLATFO-56718 It uses default memory range parsed from heap and elf to dump memory data to a file Change-Id: I2d18dbf10d80b647e547d0a35ba748f73feb0b87 Signed-off-by: xuxingliang --- tools/pynuttx/nxgdb/memdump.py | 47 ++++++++++++++++++++++++++++++++++ 1 file changed, 47 insertions(+) diff --git a/tools/pynuttx/nxgdb/memdump.py b/tools/pynuttx/nxgdb/memdump.py index a806b93110a..736786ca304 100644 --- a/tools/pynuttx/nxgdb/memdump.py +++ b/tools/pynuttx/nxgdb/memdump.py @@ -21,6 +21,7 @@ ############################################################################ import argparse +import os import re from collections import defaultdict from typing import Dict, Generator, List, Protocol, Tuple @@ -591,3 +592,49 @@ class MMFree(gdb.Command): nfree, ) ) + + +class NxDumpRAM(gdb.Command): + """Dump memory to file, similar to GDB dump memory""" + + def __init__(self): + super().__init__("dump ram", gdb.COMMAND_USER) + + def invoke(self, arg: str, from_tty: bool) -> None: + parser = argparse.ArgumentParser(description=self.__doc__) + parser.add_argument( + "-o", "--output", help="Memory dump output directory", default="memdump" + ) + parser.add_argument("-r", "--memrange", type=str, default=None) + parser.add_argument("--heap-only", action="store_true", help="Heap only") + parser.add_argument( + "--globals-only", action="store_true", help="Global variables only" + ) + + try: + args = parser.parse_args(gdb.string_to_argv(arg)) + except SystemExit: + return + + memrange = mm.get_memrange(args.memrange, args.heap_only, args.globals_only) + if not memrange: + print("No memory range found") + return + + # Enable trust-readonly flag to try to read from elf file if possible + gdb.execute("set trust-readonly-sections on") + + print(f"Dumping memory to {args.output}") + os.makedirs(args.output, exist_ok=True) + + for start, end in memrange: + print(f"Dumping memory range {start:#x} - {end:#x}") + try: + data = gdb.selected_inferior().read_memory(start, end - start) + output = os.path.join(args.output, f"{start:#x}.bin") + except gdb.MemoryError: + print(f"Failed to read memory range {start:#x} - {end:#x}") + continue + + with open(output, "wb") as f: + f.write(data) -- Gitee From e907cb5a5ea73c28ab05b15f9bc975dc471324b8 Mon Sep 17 00:00:00 2001 From: xuxingliang Date: Wed, 26 Mar 2025 20:49:59 +0800 Subject: [PATCH 154/235] nxgdb/mm: add mm find command VELAPLATFO-56718 Make it easier to find out where the pattern happends in the whole memory. Use --heap-only to search pattern only in heap memory. Use --globals-only to only search in non-heap memory. Default to search all memory. To search a string pattern in memory, (gdb) mm find \"hello\" Searching for pattern b'48656c6c6f' in memory Found pattern @ 0x23c02c4a Done (gdb) To seach a number pattern in memory, (gdb) mm find 12345678 Searching for pattern b'4e61bc' in memory Found pattern @ 0x23c025d0 Done (gdb) You can also use hex number (gdb) mm find 0x40200000 Change-Id: Id47c507bf8a98150f39bc91d82e2e604ecf4bb4c Signed-off-by: xuxingliang --- tools/pynuttx/nxgdb/memdump.py | 47 ++++++++++++++++++++++++++++++++++ 1 file changed, 47 insertions(+) diff --git a/tools/pynuttx/nxgdb/memdump.py b/tools/pynuttx/nxgdb/memdump.py index 736786ca304..45ad78ce7a7 100644 --- a/tools/pynuttx/nxgdb/memdump.py +++ b/tools/pynuttx/nxgdb/memdump.py @@ -21,6 +21,7 @@ ############################################################################ import argparse +import binascii import os import re from collections import defaultdict @@ -638,3 +639,49 @@ class NxDumpRAM(gdb.Command): with open(output, "wb") as f: f.write(data) + + +class NxMemoryFind(gdb.Command): + """Find memory address by pattern""" + + def __init__(self): + super().__init__("mm find", gdb.COMMAND_USER) + utils.alias("memfind", "mm find") + + def invoke(self, arg: str, from_tty: bool) -> None: + parser = argparse.ArgumentParser(description=self.__doc__) + parser.add_argument("pattern", type=str, help="Pattern to search") + parser.add_argument("-r", "--memrange", type=str, default=None) + parser.add_argument("--heap-only", action="store_true", help="Heap only") + parser.add_argument( + "--globals-only", action="store_true", help="Global variables only" + ) + + try: + args = parser.parse_args(gdb.string_to_argv(arg)) + except SystemExit: + return + + if args.pattern.startswith('"') and args.pattern.endswith('"'): + # Search for string + value = bytes(args.pattern[1:-1], "utf-8") + else: + # Convert to a number + value = utils.parse_arg(args.pattern) + value = value.to_bytes((value.bit_length() + 7) // 8, "little") + + print(f"Searching for pattern {binascii.hexlify(value)} in memory") + pattern = re.compile(value) + + memrange = mm.get_memrange(args.memrange, args.heap_only, args.globals_only) + for start, end in memrange: + try: + data = bytes(gdb.selected_inferior().read_memory(start, end - start)) + except gdb.MemoryError: + print(f"Failed to read memory range {start:#x} - {end:#x}") + continue + + matches = [match.start() for match in pattern.finditer(data)] + for offset in matches: + print(f"Found pattern @ {offset + start:#x}") + print("Done") -- Gitee From 037217c64b66ad01972d54e37fddf37904008d0e Mon Sep 17 00:00:00 2001 From: xuxingliang Date: Wed, 26 Mar 2025 20:51:06 +0800 Subject: [PATCH 155/235] nxgdb/mm: add mm range function to show all memories available VELAPLATFO-56718 This is for debug purpose, that can be used to show all heap memorries or sections that have ALLOC flag set and are not readonly. Change-Id: Ica03b84450c21fbf02dae5a2b4643b4c007b2f43 Signed-off-by: xuxingliang --- tools/pynuttx/nxgdb/memdump.py | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/tools/pynuttx/nxgdb/memdump.py b/tools/pynuttx/nxgdb/memdump.py index 45ad78ce7a7..b38bbc9c5ad 100644 --- a/tools/pynuttx/nxgdb/memdump.py +++ b/tools/pynuttx/nxgdb/memdump.py @@ -595,6 +595,38 @@ class MMFree(gdb.Command): ) +class NxMemoryRange(gdb.Command): + """Show RAM range of heap and sections""" + + def __init__(self): + super().__init__("mm range", gdb.COMMAND_USER) + utils.alias("memrange", "mm range") + + def invoke(self, arg, from_tty): + parser = argparse.ArgumentParser(description=self.__doc__) + parser.add_argument("--heap-only", action="store_true", help="Heap only") + parser.add_argument( + "--globals-only", action="store_true", help="Global variables only" + ) + + try: + args = parser.parse_args(gdb.string_to_argv(arg)) + except SystemExit: + return + + memrange = mm.get_memrange(None, args.heap_only, args.globals_only) + if not memrange: + print("No memory range found") + return + + header = ("start", "end", "size", "size(kB)") + formatter = "{:<20} {:<20} {:<20} {:<20}" + print(formatter.format(*header)) + for start, end in memrange: + length = end - start + print(formatter.format(hex(start), hex(end), length, f"{length/1024: .1f}")) + + class NxDumpRAM(gdb.Command): """Dump memory to file, similar to GDB dump memory""" -- Gitee From 5d38f9eb25ad47f0ab956ce02fe93d0b1ba85649 Mon Sep 17 00:00:00 2001 From: xuxingliang Date: Thu, 27 Mar 2025 15:48:39 +0800 Subject: [PATCH 156/235] nxstub/nxelf: ignore utf-8 decode error VELAPLATFO-53324 Change-Id: Ia832bd995f7d59a0ff54cb5bce3179c71623bfc9 Signed-off-by: xuxingliang --- tools/pynuttx/nxelf/elf.py | 2 +- tools/pynuttx/nxstub/target.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/tools/pynuttx/nxelf/elf.py b/tools/pynuttx/nxelf/elf.py index 98a2ad67ec0..d96d835511c 100644 --- a/tools/pynuttx/nxelf/elf.py +++ b/tools/pynuttx/nxelf/elf.py @@ -479,7 +479,7 @@ class LiefELF: output += c.tobytes() addr += 1 - return output.decode("utf-8") + return output.decode("utf-8", errors="replace") def get_inttype(self) -> Construct: return { diff --git a/tools/pynuttx/nxstub/target.py b/tools/pynuttx/nxstub/target.py index a2557929cbb..8a654e5a2e0 100644 --- a/tools/pynuttx/nxstub/target.py +++ b/tools/pynuttx/nxstub/target.py @@ -111,7 +111,7 @@ class Target: output += b address += 1 - return output.decode("utf-8") + return output.decode("utf-8", errors="replace") def update_threads(self) -> List[ThreadInfo]: """Update the latest threads information""" -- Gitee From 5cdca783d18faab2808169b1b82cbffe8f4d316b Mon Sep 17 00:00:00 2001 From: xuxingliang Date: Fri, 28 Mar 2025 15:28:17 +0800 Subject: [PATCH 157/235] nxgdb/register: fix sim32 nxthread doesn't work VELAPLATFO-57259 Add missing registers for sim32 Change-Id: I4c2bbc2b2e618b15402b82a9ac075a7e906118ad Signed-off-by: xuxingliang --- tools/pynuttx/nxreg/register.py | 24 +++++++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) diff --git a/tools/pynuttx/nxreg/register.py b/tools/pynuttx/nxreg/register.py index b05438f224e..1ba63d18487 100644 --- a/tools/pynuttx/nxreg/register.py +++ b/tools/pynuttx/nxreg/register.py @@ -162,8 +162,30 @@ g_reg_table = { ("pc", 33, REGINFO_OFFSET_AUTO), # PC ], }, + "x86": { + "architecture": ["i386", "i386:intel"], + "feature": "org.gnu.gdb.i386:x86", + "registers": [ + ("eax", 0, REGINFO_OFFSET_AUTO), + ("ecx", 1, REGINFO_OFFSET_AUTO), + ("edx", 2, REGINFO_OFFSET_AUTO), + ("ebx", 3, REGINFO_OFFSET_AUTO), + ("esp", 4, REGINFO_OFFSET_AUTO), + ("ebp", 5, REGINFO_OFFSET_AUTO), + ("esi", 6, REGINFO_OFFSET_AUTO), + ("edi", 7, REGINFO_OFFSET_AUTO), + ("eip", 8, REGINFO_OFFSET_AUTO), + ("eflags", 9, REGINFO_OFFSET_AUTO), + ("cs", 10, REGINFO_OFFSET_AUTO), + ("ss", 11, REGINFO_OFFSET_AUTO), + ("ds", 12, REGINFO_OFFSET_AUTO), + ("es", 13, REGINFO_OFFSET_AUTO), + ("fs", 14, REGINFO_OFFSET_AUTO), + ("gs", 15, REGINFO_OFFSET_AUTO), + ], + }, "x86-64": { - "architecture": ["i386", "i386:x86-64", "i386:x86-64:intel", "i386:intel"], + "architecture": ["i386:x86-64", "i386:x86-64:intel"], "feature": "org.gnu.gdb.i386:x86-64", "registers": [ ("rax", 0, REGINFO_OFFSET_AUTO), -- Gitee From d2e2dd87bdf92cad6f6a61fc27915fd2d233b746 Mon Sep 17 00:00:00 2001 From: wangmingrong1 Date: Wed, 2 Apr 2025 14:19:49 +0800 Subject: [PATCH 158/235] gdbstub: Fix alternative name for PID0 VELAPLATFO-56659 Change-Id: I0597ebb0d22f772583dc1ca6147a4089069a6f09 Signed-off-by: wangmingrong1 --- tools/pynuttx/nxgdb/utils.py | 6 ++++-- tools/pynuttx/nxstub/target.py | 12 +++++++----- 2 files changed, 11 insertions(+), 7 deletions(-) diff --git a/tools/pynuttx/nxgdb/utils.py b/tools/pynuttx/nxgdb/utils.py index 58eb8ab3d57..90857c72289 100644 --- a/tools/pynuttx/nxgdb/utils.py +++ b/tools/pynuttx/nxgdb/utils.py @@ -1238,9 +1238,11 @@ class Addr2Line(gdb.Command): self.print_backtrace(addresses) +PID0_REPLACE = get_symbol_value("PID0_REPLACE") + + def get_gdb_thread_pid(thread: gdb.InferiorThread) -> int: - idlepid = get_symbol_value("PID0_REPLACE") - return 0 if thread.ptid[1] == idlepid else thread.ptid[1] + return 0 if thread.ptid[1] == PID0_REPLACE else thread.ptid[1] def get_gdb_thread(pid: int) -> Optional[gdb.InferiorThread]: diff --git a/tools/pynuttx/nxstub/target.py b/tools/pynuttx/nxstub/target.py index 8a654e5a2e0..061732c9abb 100644 --- a/tools/pynuttx/nxstub/target.py +++ b/tools/pynuttx/nxstub/target.py @@ -59,7 +59,7 @@ class ThreadInfo: class Target: - PID0_ID = 0xFFFF + PID0_REPLACE = 0x7FFFFFFF def __init__( self, @@ -85,7 +85,7 @@ class Target: self.registers = registers or Registers(elf, arch=arch) self.memories: List[RawMemory] = [] self.arch = arch - self.pid = self.PID0_ID # Current thread PID + self.pid = self.PID0_REPLACE # Current thread PID self.remap = remap or [] for mem in memories or []: # Go through the write process to merge overlapping memory regions @@ -116,7 +116,9 @@ class Target: def update_threads(self) -> List[ThreadInfo]: """Update the latest threads information""" - self.threads = (ThreadInfo("main", self.PID0_ID, "Running", self.registers),) + self.threads = ( + ThreadInfo("main", self.PID0_REPLACE, "Running", self.registers), + ) try: pointer = self.elf.get_pointer_type() @@ -156,7 +158,7 @@ class Target: name = self._read_str(address + tcbinfo.name_off) self.logger.debug(f"loading thread: {name}, tcb@{address:#x}") pid = utils.uint16_t(data[tcbinfo.pid_off : tcbinfo.pid_off + 2]) - pid = pid if pid != 0 else self.PID0_ID + pid = pid if pid != 0 else self.PID0_REPLACE state = utils.uint8_t(data[tcbinfo.state_off : tcbinfo.state_off + 1]) state = states[state] if state < len(states) else "Unknown" @@ -205,7 +207,7 @@ class Target: if pid is None: # None is only used during our initial setup, not of GDB RSP protocol - pid = self.PID0_ID + pid = self.PID0_REPLACE for t in self.threads: if pid == t.pid: -- Gitee From d77eacb8e1ca1c8073859b573fc7b5ec46a92c88 Mon Sep 17 00:00:00 2001 From: yinshengkai Date: Wed, 2 Apr 2025 15:29:28 +0800 Subject: [PATCH 159/235] nxgdb: Generate a profile report VELAPLATFO-57486 Change-Id: I874f72ac3924b485e50565dafa7fb88f491cd471 Signed-off-by: yinshengkai --- tools/pynuttx/nxgdb/profile.py | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/tools/pynuttx/nxgdb/profile.py b/tools/pynuttx/nxgdb/profile.py index 1d16abef454..ca80b1e63fa 100644 --- a/tools/pynuttx/nxgdb/profile.py +++ b/tools/pynuttx/nxgdb/profile.py @@ -35,13 +35,22 @@ class Profile(gdb.Command): self.cProfile = import_check( "cProfile", errmsg="cProfile module not found, try gdb-multiarch.\n" ) - if not self.cProfile: + self.pstats = import_check( + "pstats", errmsg="pstats module not found, try gdb-multiarch.\n" + ) + if not self.cProfile or not self.pstats: return super().__init__("profile", gdb.COMMAND_USER) def invoke(self, args, from_tty): - self.cProfile.run(f"gdb.execute('{args}')", sort="cumulative") + self.cProfile.run(f"gdb.execute('{args}')", "results.prof") + + stats = self.pstats.Stats("results.prof") + stats.strip_dirs().sort_stats("cumulative").print_stats(20) + print( + "Generate profile file: results.prof, Execute 'snakeviz results.prof' to view the report." + ) class Time(gdb.Command): -- Gitee From 8caab98621b24a221d6c8b51568b5655f55e31ea Mon Sep 17 00:00:00 2001 From: xuxingliang Date: Thu, 3 Apr 2025 20:48:32 +0800 Subject: [PATCH 160/235] nxstub: fix g/G packet offset when first register is not zero VELAPLATFO-57719 Need to handler OFFSET_AUTO correctly. We use goffset to track the register offset. When tcb_offset is invalid, it means we cannot get value for this register. Use value of None to mark this register is not available. E.g. for x86, many registers are not avaiable. (gdb) i r eax ecx edx ebx 0x4012eef8 1074982648 esp 0xf3e2c480 0xf3e2c480 ebp 0x0 0x0 esi 0x4012eef8 1074982648 edi 0x0 0 eip 0x40031385 0x40031385 eflags cs ss ds es fs gs (gdb) Change-Id: I0277675ae89691bc7e7d219591b45d09d4596c79 Signed-off-by: xuxingliang --- tools/pynuttx/nxreg/register.py | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/tools/pynuttx/nxreg/register.py b/tools/pynuttx/nxreg/register.py index 1ba63d18487..5737364c49c 100644 --- a/tools/pynuttx/nxreg/register.py +++ b/tools/pynuttx/nxreg/register.py @@ -25,8 +25,8 @@ from typing import List, Union from construct import Array, Int8ul, Int16sl, Int16ul, PaddedString, Struct from nxelf.elf import LiefELF -UINT16_MAX = 0xFFFF -REGINFO_OFFSET_AUTO = 0 +REGINFO_OFFSET_INVALID = -2 +REGINFO_OFFSET_AUTO = -1 g_reg_table = { "arm": { @@ -408,9 +408,13 @@ class GeneralRegisters: reginfo = get_reginfo(elf) layouts = g_reg_table.get(self.arch, {}).get("registers", []) + goffset = 0 for i, (name, regnum, offset, *fixed) in enumerate(layouts): + offset = goffset if offset == REGINFO_OFFSET_AUTO else offset + goffset = offset + regsize # move to next register offset + info = next((r for r in reginfo if r.name == name), None) - if not info or info.tcb_offset == UINT16_MAX: + if not info or info.tcb_offset == REGINFO_OFFSET_INVALID: self.logger.debug(f"Register {name}({regnum}) not found in TCB") continue @@ -420,6 +424,7 @@ class GeneralRegisters: size=regsize, offset=offset, tcb_reg_off=info.tcb_offset, + value=None if info.tcb_offset == REGINFO_OFFSET_INVALID else 0, fixedvalue=fixed[0] if fixed else None, ) -- Gitee From 7902c395acab2ab83a1d085e56474225e28efbd5 Mon Sep 17 00:00:00 2001 From: xuxingliang Date: Thu, 3 Apr 2025 20:50:31 +0800 Subject: [PATCH 161/235] nxstub: enable nxreg log if enabled VELAPLATFO-57719 Change-Id: Idf9366fe6390dea68e73b5bcad7d19268a478a30 Signed-off-by: xuxingliang --- tools/pynuttx/nxstub/__init__.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tools/pynuttx/nxstub/__init__.py b/tools/pynuttx/nxstub/__init__.py index ce0a7c227af..09e7b17f69b 100644 --- a/tools/pynuttx/nxstub/__init__.py +++ b/tools/pynuttx/nxstub/__init__.py @@ -260,8 +260,8 @@ def main(args=None): logging.basicConfig( format="%(asctime)s:%(levelname)s:%(name)s:%(message)s", ) - logger = logging.getLogger(__name__) - logger.setLevel(logging.DEBUG if args.debug else logging.INFO) + logging.getLogger(__name__).setLevel(logging.DEBUG) + logging.getLogger("nxreg").setLevel(logging.DEBUG) if args.gdb: gdb = gdb_start(args) -- Gitee From 912112d44b0e031aa0471de6ed08ef33d3c5f501 Mon Sep 17 00:00:00 2001 From: xuxingliang Date: Mon, 7 Apr 2025 11:00:15 +0800 Subject: [PATCH 162/235] nxgdb/target: use detach command instead of disconnect VELAPLATFO-56229 While disconnect can only be used when target type is remote, 'detach' can be used for all below cases. - When you have attached to a process with the attach command - When you have started a process using the run command - When you have connected to a gdbserver using the target command Change-Id: I9f32d55e31d28ddad27116d3e85737bca539b7b8 Signed-off-by: xuxingliang --- tools/pynuttx/nxgdb/target.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/pynuttx/nxgdb/target.py b/tools/pynuttx/nxgdb/target.py index 9e9c6a952a8..ba53ae5089e 100644 --- a/tools/pynuttx/nxgdb/target.py +++ b/tools/pynuttx/nxgdb/target.py @@ -51,7 +51,7 @@ class Target(gdb.Command): # If currently has connection to target, disconnect it inferior = gdb.selected_inferior() if inferior and inferior.connection and inferior.connection.is_valid(): - gdb.execute("disconnect") + gdb.execute("detach", from_tty=True) def kill(event=None): if self.process: -- Gitee From a4cb653bc427b531f682e8452bdf6e419565c6e2 Mon Sep 17 00:00:00 2001 From: yangao1 Date: Thu, 3 Apr 2025 14:14:15 +0800 Subject: [PATCH 163/235] nxgdb/dmesg.py:remove print when config is not open VELAPLATFO-52584 Change-Id: I25a9e139685164384c65f622148998132430275b Signed-off-by: yangao1 --- tools/pynuttx/nxgdb/dmesg.py | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/tools/pynuttx/nxgdb/dmesg.py b/tools/pynuttx/nxgdb/dmesg.py index 84b7d66200f..0f7b5967b73 100644 --- a/tools/pynuttx/nxgdb/dmesg.py +++ b/tools/pynuttx/nxgdb/dmesg.py @@ -81,5 +81,8 @@ class Dmesg(gdb.Command): ramlog = self._get_ramlog() rpmsg_syslog = self._get_rpmsg_syslog() - print(f"RAM log:{ramlog}\n---END of RAMLOG") - print(f"RPMSG syslog:{rpmsg_syslog}\n---END of RPMSG SYSLOG---") + if CONFIG_RAMLOG_SYSLOG: + print(f"RAM log:{ramlog}\n---END of RAMLOG") + + if CONFIG_SYSLOG_RPMSG: + print(f"RPMSG syslog:{rpmsg_syslog}\n---END of RPMSG SYSLOG---") -- Gitee From 10b28350f87b824fd45de9122467d1f4b4385219 Mon Sep 17 00:00:00 2001 From: yinshengkai Date: Wed, 2 Apr 2025 15:24:18 +0800 Subject: [PATCH 164/235] pynuttx: Split symbol parsing into separate functions VELAPLATFO-57486 Signed-off-by: yinshengkai None: + """Resolve symbol information for the given address""" + if not address: + return + + # Check cache first + if int(address) in g_backtrace_cache: + cached = g_backtrace_cache[int(address)] + self.address, self.func, self._symtab_and_line = cached + return + + # Convert to proper gdb.Value if needed + if type(address) is int: + address = gdb.Value(address) + + # Ensure we have a pointer type + if address.type.code is not gdb.TYPE_CODE_PTR: + address = address.cast(gdb.lookup_type("void").pointer()) + + # Get symbol information + self.address = int(address) + self._symtab_and_line = gdb.find_pc_line(int(address)) + if not self.is_valid(): + return + + self.func = address.format_string(symbols=True, address=False) + + # Cache the result + result = (self.address, self.func, self._symtab_and_line) + g_backtrace_cache[self.address] = result + + def is_valid(self) -> bool: + return ( + self._symtab_and_line + and self._symtab_and_line.is_valid() + and self._symtab_and_line.symtab + and self._symtab_and_line.symtab.is_valid() + ) + + @property + def filename(self) -> str: + if not self.is_valid(): + return "" + return str(self._symtab_and_line.symtab.fullname()) + + @property + def line(self) -> int: + if not self.is_valid(): + return 0 + return int(self._symtab_and_line.line) + + def __repr__(self) -> str: + return ( + f"" + ) + + class Backtrace: """ Convert addresses to backtrace @@ -135,12 +199,12 @@ class Backtrace: backtrace = Backtrace(addresses=[0x4001, 0x4002, 0x4003]) # Access converted backtrace - addr, func, source = backtrace[0] - remaining = backtrace[1:] # Return list of (addr, func, source) + addr, func, file, line = backtrace[0] + remaining = backtrace[1:] # Return list of (addr, func, file, line) # Iterate over backtrace - for addr, func, source in backtrace: - print(addr, func, source) + for addr, func, file, line in backtrace: + print(addr, func, file, line) # Append more addresses to convert backtrace.append(0x40001234) @@ -177,38 +241,19 @@ class Backtrace: def append(self, addr: Union[gdb.Value, int]) -> None: """Append an address to the backtrace""" - if result := self.convert(addr): - self.backtrace.append(result) + if result := Symbol(addr): + self.backtrace.append( + (result.address, result.func, result.filename, result.line) + ) self._formatted = None # Clear cached result - def convert(self, addr: Union[gdb.Value, int]) -> Tuple[int, str, str]: - """Convert an address to function and source""" - if not addr: - return None - - if int(addr) in g_backtrace_cache: - return g_backtrace_cache[int(addr)] - - if type(addr) is int: - addr = gdb.Value(addr) - - if addr.type.code is not gdb.TYPE_CODE_PTR: - addr = addr.cast(gdb.lookup_type("void").pointer()) - - func = addr.format_string(symbols=True, address=False) - sym = gdb.find_pc_line(int(addr)) - source = str(sym.symtab) + ":" + str(sym.line) - result = (int(addr), func, source) - g_backtrace_cache[int(addr)] = result - return result - @property def formatted(self): """Return the formatted backtrace string list""" if not self._formatted: self._formatted = [ - self.formatter.format(hex(addr), func, source) - for addr, func, source in self.backtrace + self.formatter.format(hex(addr), func, f"{file}:{line}") + for addr, func, file, line in self.backtrace ] return self._formatted -- Gitee From 65fbf1679d5c96175ff332d6f110e01b6df078da Mon Sep 17 00:00:00 2001 From: yinshengkai Date: Thu, 3 Apr 2025 12:30:09 +0800 Subject: [PATCH 165/235] pynuttx: memory range adds idle stack and heap_s VELAPLATFO-57486 Change-Id: I995761e9cc3f29db29c956edaced0061f9bb7d30 Signed-off-by: yinshengkai --- tools/pynuttx/nxgdb/mm.py | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/tools/pynuttx/nxgdb/mm.py b/tools/pynuttx/nxgdb/mm.py index 1dfa6e3fc66..2c55322fd98 100644 --- a/tools/pynuttx/nxgdb/mm.py +++ b/tools/pynuttx/nxgdb/mm.py @@ -649,16 +649,24 @@ def memory_range(heap=True, globals=True) -> List[Tuple[int, int]]: memranges.append((start, end)) + idle_topstack = int(gdb.parse_and_eval("g_idle_topstack")) + idle_stacksize = int(gdb.parse_and_eval("CONFIG_IDLETHREAD_STACKSIZE")) + memranges.append((idle_topstack - idle_stacksize, idle_topstack)) + # Get heaps from memdump if heap: for heap in get_heaps(): for i in range(heap.nregions): start = int(heap["mm_heapstart"][i]) - end = int(heap["mm_heapend"][i]) + end = int(heap["mm_heapend"][i]) + MMNode.MM_SIZEOF_ALLOCNODE if start == end: continue + # For the first region in the heap we need to compensate for the heap_s size + if i == 0: + start = int(heap.address) + for r in memranges: # If the address range is already in memranges, skip if r[0] <= start and r[1] >= end: -- Gitee From 3373d4c8da4b49d91f14e77d4a84fd71be17bad1 Mon Sep 17 00:00:00 2001 From: yinshengkai Date: Wed, 2 Apr 2025 22:55:14 +0800 Subject: [PATCH 166/235] pynuttx: add memory visualize VELAPLATFO-57486 Change-Id: I7d4e356153687b1d09aa8fa9ab2aefe8430ffc8d Signed-off-by: yinshengkai --- tools/pynuttx/nxgdb/memdump.py | 101 +++++++++++++++++++++++++++++++++ tools/pynuttx/nxgdb/mm.py | 45 +++++++++++++++ tools/pynuttx/requirements.txt | 2 + 3 files changed, 148 insertions(+) diff --git a/tools/pynuttx/nxgdb/memdump.py b/tools/pynuttx/nxgdb/memdump.py index b38bbc9c5ad..a006f554413 100644 --- a/tools/pynuttx/nxgdb/memdump.py +++ b/tools/pynuttx/nxgdb/memdump.py @@ -532,6 +532,107 @@ class MMMap(gdb.Command): gdb.write(f"Memory map saved to {output}\n") +class MMVisualize(gdb.Command): + """Generates a memory treemap, showing all backtrace statistics""" + + def __init__(self): + self.backtrace_depth = mm.CONFIG_MM_RECORD_STACK + if self.backtrace_depth <= 0: + gdb.write( + "Without mm record backtrace enabled, visualization is not possible" + ) + return + + super().__init__("mm visualize", gdb.COMMAND_USER) + utils.alias("memvisualize", "mm visualize") + self.px = utils.import_check( + "plotly.express", errmsg="Please pip install plotly\n" + ) + self.pd = utils.import_check("pandas", errmsg="Please pip install pandas\n") + + def invoke(self, args, from_tty): + parser = argparse.ArgumentParser(description=self.__doc__) + parser.add_argument( + "-o", + "--output", + type=str, + default="mm_visualize", + help="html output file", + ) + parser.add_argument( + "--heap", type=str, help="Which heap's pool to show", default=None + ) + + try: + args = parser.parse_args(gdb.string_to_argv(args)) + except SystemExit: + return + + nodes = mm.get_nodes_dict() + df = self.pd.DataFrame.from_records(nodes) + + # Only show used nodes, exclude all free nodes + df = df[~df["free"]] + + # Merge all nodes with the same pid and backtrace + df = ( + df.groupby(["backtrace", "pid"], as_index=False) + .agg( + { + "name": lambda x: x.iloc[0], + "address": "any", + "size": "sum", + "pid": "first", + "from_pool": "first", + } + ) + .reset_index() + ) + + for i in range(self.backtrace_depth): + df[f"stack_{i}"] = df["backtrace"].apply( + lambda x: "Unkown" if not x[i] else utils.Symbol(x[i]).func + ) + + # Drop the backtrace column + df = df.drop(columns=["backtrace"]) + + # Reorder the backtrace to ensure it is displayed in the correct format in the UI. + # For example, a,b,c,0,U,U,U,U generates U,U,U,U,U,a,b,c + stack_columns = [f"stack_{i}" for i in range(8)] + for index, row in df.iterrows(): + stack_values = row[stack_columns].tolist() + unknowns = [val for val in stack_values if val == "Unkown"] + non_unknowns = [val for val in stack_values if val != "Unkown"] + new_stack_values = unknowns + non_unknowns + df.loc[index, stack_columns] = new_stack_values + + # Generate the treemap + stack_cols = [f"stack_{i}" for i in range(self.backtrace_depth - 1, -1, -1)] + fig = self.px.treemap( + df, + path=stack_cols, + values="size", + hover_data=["pid", "from_pool"], + title="Memory Allocation", + ) + + fig.update_layout( + margin=dict(t=50, l=25, r=25, b=25), + coloraxis_colorbar=dict(title="Size (bytes)"), + ) + fig.update_traces( + maxdepth=3, + texttemplate="%{label}
%{value:,d} bytes", + textposition="middle center", + marker=dict(line=dict(width=1, color="DarkGray")), + ) + + path = args.output + ".html" + fig.write_html(path) + gdb.write(f"Memory map saved to Memory visualizations saved to {path}\n") + + class MMFree(gdb.Command): """Show heap statistics, same as device command free""" diff --git a/tools/pynuttx/nxgdb/mm.py b/tools/pynuttx/nxgdb/mm.py index 2c55322fd98..eb26d7845ed 100644 --- a/tools/pynuttx/nxgdb/mm.py +++ b/tools/pynuttx/nxgdb/mm.py @@ -701,6 +701,51 @@ def get_memrange( return memory_range(heap=not globals_only, globals=not heap_only) +def get_nodes_dict(): + """ + Return dict of all memory nodes, including memory pool. + """ + + # If there is a cached result, return it directly + if hasattr(get_nodes_dict, "_cached_nodes"): + return get_nodes_dict._cached_nodes + + nodes = [] + for heap in get_heaps(): + nodes.extend( + { + "name": heap.name, + "address": node.address, + "size": node.nodesize, + "seqno": node.seqno, + "pid": node.pid, + "free": node.is_free, + "from_pool": False, + "backtrace": node.backtrace, + } + for node in heap.nodes + ) + + for pool in get_pools([heap]): + nodes.extend( + { + "name": f"{heap.name}@{blk.nodesize}pool", + "address": blk.address, + "size": blk.nodesize, + "seqno": blk.seqno, + "pid": blk.pid, + "free": blk.is_free, + "from_pool": True, + "backtrace": blk.backtrace, + } + for blk in pool.blks + ) + + # Cache the result + get_nodes_dict._cached_nodes = nodes + return nodes + + class MMHeapInfo(gdb.Command): """Show basic heap information""" diff --git a/tools/pynuttx/requirements.txt b/tools/pynuttx/requirements.txt index ec6fb47f086..f3e81ff2134 100644 --- a/tools/pynuttx/requirements.txt +++ b/tools/pynuttx/requirements.txt @@ -5,5 +5,7 @@ debugpy lief matplotlib numpy +pandas pillow +plotly pyelftools -- Gitee From 495179270aab5e50401176d38c1641077c57822c Mon Sep 17 00:00:00 2001 From: yinshengkai Date: Fri, 21 Mar 2025 18:31:42 +0800 Subject: [PATCH 167/235] nxgdb: add sq_for_every VELAPLATFO-56500 Change-Id: I33c38b143d3c213a8e3c66b15c5d899377ca5eba Signed-off-by: yinshengkai --- tools/pynuttx/nxgdb/lists.py | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/tools/pynuttx/nxgdb/lists.py b/tools/pynuttx/nxgdb/lists.py index 0c6222f1fb3..b90bd16d2e8 100644 --- a/tools/pynuttx/nxgdb/lists.py +++ b/tools/pynuttx/nxgdb/lists.py @@ -247,6 +247,25 @@ def sq_count(sq) -> int: return sq_check(sq, verbose=False) +def sq_for_every(sq, entry=None): + """Iterate over a singly linked list""" + if sq.type == sq_queue_type.pointer(): + sq = sq.dereference() + elif sq.type != sq_queue_type: + gdb.write("Must be struct sq_queue not {}".format(sq.type)) + return + + if sq["head"] == 0: + return + + if not entry: + entry = sq["head"].dereference() + + while entry.address: + yield entry + entry = entry["flink"].dereference() + + def dq_for_every(dq, entry=None): """Iterate over a doubly linked list""" if dq.type == dq_queue_type.pointer(): -- Gitee From 8a2c690f9cf9a6abdc9091664629a7883a719809 Mon Sep 17 00:00:00 2001 From: xuxingliang Date: Tue, 8 Apr 2025 17:22:52 +0800 Subject: [PATCH 168/235] nxreg: fix wrong offset in GDB g packet VELAPLATFO-56229 The next register g/G offset calculation is wrong, it should be the current register offset plus register size. Change-Id: I781ce0bbb4b9a4f475ea60dc34d9eefcbc391109 Signed-off-by: xuxingliang --- tools/pynuttx/nxreg/register.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tools/pynuttx/nxreg/register.py b/tools/pynuttx/nxreg/register.py index 5737364c49c..1db7266e2a1 100644 --- a/tools/pynuttx/nxreg/register.py +++ b/tools/pynuttx/nxreg/register.py @@ -497,7 +497,7 @@ class GeneralRegisters: else: reply += hexlify(bytes(reg)) - offset += reg.offset + reg.size + offset = reg.offset + reg.size return reply def from_g(self, data: bytes): @@ -509,7 +509,7 @@ class GeneralRegisters: f"Parse {reg.name}({reg.regnum}) from {offset}, data: {data[offset:offset+reg.size]}" ) reg.value = data[offset : offset + reg.size] - offset += reg.size + offset = reg.offset + reg.size def __iter__(self): return iter(self._registers) -- Gitee From 16d752cb9e1a2120fbffa12a11f0a10d8c2e3359 Mon Sep 17 00:00:00 2001 From: xuxingliang Date: Tue, 8 Apr 2025 17:25:33 +0800 Subject: [PATCH 169/235] nxreg: align variable name with C code VELAPLATFO-56229 Only renaming, no functional change. toffset: register offset in TCB context goffset: register offset in GDB g/G packet Change-Id: Iee0b15ed9accaf023923c7a6fe0408b0b79871d5 Signed-off-by: xuxingliang --- tools/pynuttx/nxgdb/thread.py | 4 +-- tools/pynuttx/nxreg/register.py | 52 +++++++++++++++++---------------- 2 files changed, 29 insertions(+), 27 deletions(-) diff --git a/tools/pynuttx/nxgdb/thread.py b/tools/pynuttx/nxgdb/thread.py index 16f56c26d8d..a9a8f828502 100644 --- a/tools/pynuttx/nxgdb/thread.py +++ b/tools/pynuttx/nxgdb/thread.py @@ -135,8 +135,8 @@ class RegInfoCommand(gdb.Command): formatter.format( register.name, register.regnum, - register.offset, - register.tcb_reg_off, + register.goffset, + register.toffset, ) ) diff --git a/tools/pynuttx/nxreg/register.py b/tools/pynuttx/nxreg/register.py index 1db7266e2a1..ec746c2d4ad 100644 --- a/tools/pynuttx/nxreg/register.py +++ b/tools/pynuttx/nxreg/register.py @@ -306,16 +306,16 @@ g_reg_table = { class RegInfo: - def __init__(self, name, size, tcb_offset=0): + def __init__(self, name, size, toffset=0): self.name = name self.size = size - self.tcb_offset = tcb_offset + self.toffset = toffset def __str__(self): return f"{self.name}({self.size})" def __repr__(self): - return f"REG({self.name}, {self.size}, {self.tcb_offset})" + return f"REG({self.name}, {self.size}, {self.toffset})" def get_reginfo(elf: LiefELF) -> List[RegInfo]: @@ -340,19 +340,22 @@ def get_reginfo(elf: LiefELF) -> List[RegInfo]: class Register: def __init__( - self, name, regnum, size: int, offset=0, tcb_reg_off=0, value=0, fixedvalue=None + self, name, regnum, size: int, goffset=0, toffset=0, value=0, fixedvalue=None ): self.name = name self.regnum = regnum self.size = size # size in bytes - self.offset = offset - self.tcb_reg_off = tcb_reg_off + assert ( + goffset != REGINFO_OFFSET_AUTO + ) # Must be the final processed offset for GDB g/G packet + self.goffset = goffset + self.toffset = toffset self._value = value self.fixedvalue = fixedvalue self.logger = logging.getLogger(__name__) def __str__(self): - return f"{self.name}({self.regnum}, size:{self.size}, offset:{self.offset},{self.tcb_reg_off} value:{self.value:#x})" + return f"{self.name}({self.regnum}, size:{self.size}, offset:{self.goffset},{self.toffset} value:{self.value:#x})" def __repr__(self): return self.__str__() @@ -414,7 +417,7 @@ class GeneralRegisters: goffset = offset + regsize # move to next register offset info = next((r for r in reginfo if r.name == name), None) - if not info or info.tcb_offset == REGINFO_OFFSET_INVALID: + if not info or info.toffset == REGINFO_OFFSET_INVALID: self.logger.debug(f"Register {name}({regnum}) not found in TCB") continue @@ -422,15 +425,15 @@ class GeneralRegisters: name=name, regnum=regnum, size=regsize, - offset=offset, - tcb_reg_off=info.tcb_offset, - value=None if info.tcb_offset == REGINFO_OFFSET_INVALID else 0, + goffset=offset, + toffset=info.toffset, + value=None if info.toffset == REGINFO_OFFSET_INVALID else 0, fixedvalue=fixed[0] if fixed else None, ) self._registers.append(register) self.logger.debug( - f"Register {name}({regnum}) offset: {offset}, tcb_off: {register.tcb_reg_off}" + f"Register {name}({regnum}) offset: {offset}, tcb_off: {register.toffset}" ) self._registers.sort(key=lambda x: x.regnum) @@ -479,7 +482,7 @@ class GeneralRegisters: xcpregs = self.readmem(addr, self.xcp_reg_size) if xcpregs: for reg in self._registers: - reg.value = xcpregs[reg.tcb_reg_off : reg.tcb_reg_off + reg.size] + reg.value = xcpregs[reg.toffset : reg.toffset + reg.size] else: raise ValueError("No valid source to load register values.\n") return self # allow to build and use Register().load() directly @@ -487,29 +490,28 @@ class GeneralRegisters: def to_g(self): """Return GDB RSP g packet""" reply = b"" - offset = 0 + goffset = 0 for reg in self._registers: - if reg.offset and reg.offset != offset: - reply += b"xx" * (reg.offset - offset) + if reg.goffset != goffset: + reply += b"xx" * (reg.goffset - goffset) if not reg.has_value: reply += b"xx" * reg.size else: reply += hexlify(bytes(reg)) - offset = reg.offset + reg.size + goffset = reg.goffset + reg.size return reply def from_g(self, data: bytes): """Parse GDB RSP G packet""" - offset = 0 for reg in self._registers: - offset = reg.offset if reg.offset else offset + goffset = reg.goffset self.logger.debug( - f"Parse {reg.name}({reg.regnum}) from {offset}, data: {data[offset:offset+reg.size]}" + f"Parse {reg.name}({reg.regnum}) from {goffset}, data: {data[goffset:goffset+reg.size]}" ) - reg.value = data[offset : offset + reg.size] - offset = reg.offset + reg.size + reg.value = data[goffset : goffset + reg.size] + goffset = reg.goffset + reg.size def __iter__(self): return iter(self._registers) @@ -538,7 +540,7 @@ class TricoreRegisters(GeneralRegisters): for name in xcp_table[:lower_count]: reg = self.get(name=name) - reg.value = xcpregs[reg.tcb_reg_off : reg.tcb_reg_off + reg.size] + reg.value = xcpregs[reg.toffset : reg.toffset + reg.size] if name == "pcx": lpcx = reg.value @@ -557,9 +559,9 @@ class TricoreRegisters(GeneralRegisters): xcpregs = self.readmem(csa2addr(lpcx), upper_count * 4) for name in xcp_table[lower_count:]: reg = self.get(name=name) - if reg.tcb_reg_off + reg.size > len(xcpregs): + if reg.toffset + reg.size > len(xcpregs): raise ValueError("No valid source to load register values.\n") - reg.value = xcpregs[reg.tcb_reg_off : reg.tcb_reg_off + reg.size] + reg.value = xcpregs[reg.toffset : reg.toffset + reg.size] return self -- Gitee From 7be9b2f0f8c1469bf2b0b52b46b194a07227ad6b Mon Sep 17 00:00:00 2001 From: xuxingliang Date: Tue, 8 Apr 2025 11:30:45 +0800 Subject: [PATCH 170/235] nxgdb: remove empty registers.py VELAPLATFO-56229 Now we use nxreg module to handle registers. Change-Id: Icf6077b4ae8e3c4af2204dda22027bed88d2b59d Signed-off-by: xuxingliang --- tools/pynuttx/nxstub/registers.py | 21 --------------------- 1 file changed, 21 deletions(-) delete mode 100644 tools/pynuttx/nxstub/registers.py diff --git a/tools/pynuttx/nxstub/registers.py b/tools/pynuttx/nxstub/registers.py deleted file mode 100644 index 94c6f733370..00000000000 --- a/tools/pynuttx/nxstub/registers.py +++ /dev/null @@ -1,21 +0,0 @@ -############################################################################ -# tools/pynuttx/nxstub/registers.py -# -# SPDX-License-Identifier: Apache-2.0 -# -# Licensed to the Apache Software Foundation (ASF) under one or more -# contributor license agreements. See the NOTICE file distributed with -# this work for additional information regarding copyright ownership. The -# ASF licenses this file to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance with the -# License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# -############################################################################ -- Gitee From d5b8317ad9b48162e15001248b4e2f7640a405dd Mon Sep 17 00:00:00 2001 From: xuxingliang Date: Tue, 8 Apr 2025 11:55:16 +0800 Subject: [PATCH 171/235] nxgdb: rename target stub to target nxstub VELAPLATFO-56229 nxstub is the module name we used in pynuttx. nxstub means specifically for NuttX. Thus it's more suitable. Add alias for backward compatibility. Change-Id: I264ce9bd9ef4b85ab54b5c6563e9971a2915c2a8 Signed-off-by: xuxingliang --- tools/pynuttx/nxgdb/target.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/tools/pynuttx/nxgdb/target.py b/tools/pynuttx/nxgdb/target.py index ba53ae5089e..f89ec7fd157 100644 --- a/tools/pynuttx/nxgdb/target.py +++ b/tools/pynuttx/nxgdb/target.py @@ -25,12 +25,15 @@ import multiprocessing import gdb import nxstub +from . import utils + class Target(gdb.Command): """Use nxstub to parse crash log dump, core dump or memory dump, as target.""" def __init__(self): super().__init__("target stub", gdb.COMMAND_USER) + utils.alias("target nxstub", "target stub") self.process = None def invoke(self, args, from_tty): -- Gitee From 0a37dbc1ff8dce68f40e7a85d0ed9b9dc8ed8764 Mon Sep 17 00:00:00 2001 From: yinshengkai Date: Fri, 21 Mar 2025 15:12:11 +0800 Subject: [PATCH 172/235] pynuttx: free command displays mempool memory VELAPLATFO-56500 name total used free maxused maxfree nused nfree Umem 67108864 1879984 65228880 1892608 65208224 20 6 Umem@mempool 40960 6976 33984 19640 21320 48 81 Change-Id: I1df73968b2e10b39e9ba8d821c616bbaa487dde9 Signed-off-by: yinshengkai --- tools/pynuttx/nxgdb/memdump.py | 42 +++++++++++++++++++++++++++++----- tools/pynuttx/nxgdb/mm.py | 6 +++++ 2 files changed, 42 insertions(+), 6 deletions(-) diff --git a/tools/pynuttx/nxgdb/memdump.py b/tools/pynuttx/nxgdb/memdump.py index a006f554413..00cfe1c3af2 100644 --- a/tools/pynuttx/nxgdb/memdump.py +++ b/tools/pynuttx/nxgdb/memdump.py @@ -672,12 +672,28 @@ class MMFree(gdb.Command): heap_used += nodesize nused += 1 - mempool_free = sum( - blk.nodesize - for pool in mm.get_pools([heap]) - for blk in pool.blks - if blk.is_free - ) + mempool_total = 0 + mempool_maxused = 0 + mempool_used = 0 + mempool_nused = 0 + mempool_nfree = 0 + mempool_free = 0 + + if mm_pool := heap.mm_mpool: + mpool = mm.MemPoolMultiple(mm_pool) + + for chunk in mpool.chunks: + mempool_total += int(chunk.end) - int(chunk.start) + + for pool in mpool.pools: + mempool_maxused += pool.total + for blk in pool.blks: + if blk.is_free: + mempool_free += blk.nodesize + mempool_nfree += 1 + else: + mempool_used += blk.nodesize + mempool_nused += 1 total = heap.heapsize + mm_heap_s.sizeof heap_used += mm_heap_s.sizeof # struct overhead @@ -695,6 +711,20 @@ class MMFree(gdb.Command): ) ) + if mempool_total: + print( + formatter.format( + f"{heap.name}@mempool", + mempool_total, + mempool_used, + mempool_total - mempool_used, + mempool_maxused, + mempool_total - mempool_maxused, + mempool_nused, + mempool_nfree, + ) + ) + class NxMemoryRange(gdb.Command): """Show RAM range of heap and sections""" diff --git a/tools/pynuttx/nxgdb/mm.py b/tools/pynuttx/nxgdb/mm.py index eb26d7845ed..ab298ce5c99 100644 --- a/tools/pynuttx/nxgdb/mm.py +++ b/tools/pynuttx/nxgdb/mm.py @@ -372,6 +372,12 @@ class MemPoolMultiple(Value, p.MemPoolMultiple): def free(self) -> int: return sum(pool.free for pool in self.pools) + @property + def chunks(self) -> Generator[MemPoolBlock, None, None]: + for chunk in lists.sq_for_every(self.chunk_queue): + chunk = chunk.cast(gdb.lookup_type("struct mpool_chunk_s")) + yield chunk + class MMNode(gdb.Value, p.MMFreeNode): """ -- Gitee From a45b7ed79e3b2f1c3e33320817dddc5cb217b71e Mon Sep 17 00:00:00 2001 From: ganjing Date: Mon, 7 Apr 2025 17:18:12 +0800 Subject: [PATCH 173/235] feat: uname has added a diagnostic interface VELAPLATFO-57782 Change-Id: Ifd51c95db51d78f020a4d283758faf0b8f2427fa Signed-off-by: ganjing --- tools/pynuttx/nxgdb/uname.py | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/tools/pynuttx/nxgdb/uname.py b/tools/pynuttx/nxgdb/uname.py index fc8a3e156a5..3fe84cb5de9 100644 --- a/tools/pynuttx/nxgdb/uname.py +++ b/tools/pynuttx/nxgdb/uname.py @@ -118,3 +118,12 @@ class UnameCommand(gdb.Command): print(machine) if args.version: print(tool_version) + + def diagnose(self, *args, **kwargs): + return { + "title": "Uname Report", + "summary": "dump the kernel version number", + "command": "uname", + "result": "info", + "message": gdb.execute("uname -a", to_string=True), + } -- Gitee From 97f5af7c41468383d069c583a83b3c3d29c2024a Mon Sep 17 00:00:00 2001 From: ganjing Date: Wed, 9 Apr 2025 11:01:23 +0800 Subject: [PATCH 174/235] feat: add gdb.Command not repeat decorator VELAPLATFO-57864 Change-Id: I4c4cc26a35e53475ed36763e052dba983bda6a5e Signed-off-by: ganjing --- tools/pynuttx/nxgdb/circbuf.py | 1 + tools/pynuttx/nxgdb/debug.py | 1 + tools/pynuttx/nxgdb/diagnose.py | 1 + tools/pynuttx/nxgdb/dmesg.py | 1 + tools/pynuttx/nxgdb/elf.py | 3 ++- tools/pynuttx/nxgdb/fs.py | 6 ++++++ tools/pynuttx/nxgdb/gcore.py | 1 + tools/pynuttx/nxgdb/irq.py | 1 + tools/pynuttx/nxgdb/kasan.py | 1 + tools/pynuttx/nxgdb/libuv.py | 1 + tools/pynuttx/nxgdb/lists.py | 3 +++ tools/pynuttx/nxgdb/memcheck.py | 1 + tools/pynuttx/nxgdb/memclassify.py | 1 + tools/pynuttx/nxgdb/memdump.py | 8 ++++++++ tools/pynuttx/nxgdb/memleak.py | 1 + tools/pynuttx/nxgdb/mm.py | 2 ++ tools/pynuttx/nxgdb/net.py | 2 ++ tools/pynuttx/nxgdb/notesnap.py | 1 + tools/pynuttx/nxgdb/nxcrash/busyloop.py | 1 + tools/pynuttx/nxgdb/nxcrash/deadlock.py | 1 + tools/pynuttx/nxgdb/nxcrash/stackoverflow.py | 1 + tools/pynuttx/nxgdb/nxcrash/thread.py | 1 + tools/pynuttx/nxgdb/pginfo.py | 3 ++- tools/pynuttx/nxgdb/pm.py | 1 + tools/pynuttx/nxgdb/profile.py | 4 +++- tools/pynuttx/nxgdb/rpmsg.py | 1 + tools/pynuttx/nxgdb/stack.py | 1 + tools/pynuttx/nxgdb/target.py | 1 + tools/pynuttx/nxgdb/thread.py | 6 ++++++ tools/pynuttx/nxgdb/tlsdump.py | 1 + tools/pynuttx/nxgdb/uname.py | 1 + tools/pynuttx/nxgdb/uorb.py | 1 + tools/pynuttx/nxgdb/utils.py | 14 ++++++++++++++ tools/pynuttx/nxgdb/wdog.py | 1 + tools/pynuttx/nxgdb/wqueue.py | 1 + 35 files changed, 73 insertions(+), 3 deletions(-) diff --git a/tools/pynuttx/nxgdb/circbuf.py b/tools/pynuttx/nxgdb/circbuf.py index 3432fe471c5..258be09349d 100644 --- a/tools/pynuttx/nxgdb/circbuf.py +++ b/tools/pynuttx/nxgdb/circbuf.py @@ -148,6 +148,7 @@ class CircBufInfo(gdb.Command): def __init__(self): super().__init__("circbuf", gdb.COMMAND_USER) + @utils.dont_repeat_decorator def invoke(self, arg: str, from_tty: bool) -> None: parser = argparse.ArgumentParser(description="Dump circle buffer information") parser.add_argument( diff --git a/tools/pynuttx/nxgdb/debug.py b/tools/pynuttx/nxgdb/debug.py index 35858b61d2c..1514cbf0e30 100644 --- a/tools/pynuttx/nxgdb/debug.py +++ b/tools/pynuttx/nxgdb/debug.py @@ -38,6 +38,7 @@ class DebugPy(gdb.Command): self.debugpy = debugpy super().__init__("debugpy", gdb.COMMAND_USER) + @utils.dont_repeat_decorator def invoke(self, args, from_tty): debugpy = self.debugpy if debugpy.is_client_connected(): diff --git a/tools/pynuttx/nxgdb/diagnose.py b/tools/pynuttx/nxgdb/diagnose.py index 2ed088c02ef..cd53941ced6 100644 --- a/tools/pynuttx/nxgdb/diagnose.py +++ b/tools/pynuttx/nxgdb/diagnose.py @@ -40,6 +40,7 @@ class DiagnoseReport(gdb.Command): def __init__(self): super().__init__("diagnose report", gdb.COMMAND_USER) + @utils.dont_repeat_decorator def invoke(self, args, from_tty): parser = argparse.ArgumentParser(description=self.__doc__) parser.add_argument( diff --git a/tools/pynuttx/nxgdb/dmesg.py b/tools/pynuttx/nxgdb/dmesg.py index 0f7b5967b73..bd6100d2cce 100644 --- a/tools/pynuttx/nxgdb/dmesg.py +++ b/tools/pynuttx/nxgdb/dmesg.py @@ -77,6 +77,7 @@ class Dmesg(gdb.Command): "message": f"RAM log:\n{ramlog}\n RPMSG syslog:{rpmsg_syslog}", } + @utils.dont_repeat_decorator def invoke(self, args, from_tty): ramlog = self._get_ramlog() rpmsg_syslog = self._get_rpmsg_syslog() diff --git a/tools/pynuttx/nxgdb/elf.py b/tools/pynuttx/nxgdb/elf.py index 51d1c142c55..e826d1ce96e 100644 --- a/tools/pynuttx/nxgdb/elf.py +++ b/tools/pynuttx/nxgdb/elf.py @@ -30,7 +30,7 @@ try: except ImportError: print('Package missing, please do "pip install lief"') -from .utils import get_tcbs, has_field +from .utils import dont_repeat_decorator, get_tcbs, has_field CONFIG_ARCH_USE_SEPARATED_SECTION = has_field("struct module_s", "sectalloc") @@ -40,6 +40,7 @@ class ElfImport(gdb.Command): if has_field("struct task_group_s", "tg_bininfo"): super().__init__("elfimport", gdb.COMMAND_USER) + @dont_repeat_decorator def invoke(self, args, from_tty): parser = argparse.ArgumentParser(description="import elf symbols to gdb") parser.add_argument("elfpath", type=str, help="elf file path, etc: apps/bin") diff --git a/tools/pynuttx/nxgdb/fs.py b/tools/pynuttx/nxgdb/fs.py index 27be04c889d..68c868454bb 100644 --- a/tools/pynuttx/nxgdb/fs.py +++ b/tools/pynuttx/nxgdb/fs.py @@ -321,6 +321,7 @@ class Fdinfo(gdb.Command): "message": output, } + @utils.dont_repeat_decorator def invoke(self, arg, from_tty): parser = argparse.ArgumentParser( description="Get fdinfo for a process or all processes." @@ -357,6 +358,7 @@ class Mount(gdb.Command): "message": output or "No mount", } + @utils.dont_repeat_decorator def invoke(self, args, from_tty): self.mount_count = 0 nodes = filter( @@ -459,6 +461,7 @@ class ForeachInode(gdb.Command): "message": output, } + @utils.dont_repeat_decorator def invoke(self, args, from_tty): args = self.parse_arguments(args.split(" ")) if not args: @@ -513,6 +516,7 @@ class InfoShmfs(gdb.Command): "message": output or "No InfoShmfs", } + @utils.dont_repeat_decorator def invoke(self, args, from_tty): self.total_size = 0 self.block_count = 0 @@ -605,6 +609,7 @@ class InfoRomfs(gdb.Command): "message": output or "No romfs information", } + @utils.dont_repeat_decorator def invoke(self, args, from_tty): args = self.parse_arguments(gdb.string_to_argv(args)) nodes = filter(fstype_filter("romfs"), foreach_inode()) @@ -718,6 +723,7 @@ class InfoYaffs(gdb.Command): "message": output or "No yaffs information", } + @utils.dont_repeat_decorator def invoke(self, args, from_tty): args = self.parse_arguments(gdb.string_to_argv(args)) nodes = filter(fstype_filter("yaffs"), foreach_inode()) diff --git a/tools/pynuttx/nxgdb/gcore.py b/tools/pynuttx/nxgdb/gcore.py index 3d68fb85187..83d7c80f5a9 100644 --- a/tools/pynuttx/nxgdb/gcore.py +++ b/tools/pynuttx/nxgdb/gcore.py @@ -79,6 +79,7 @@ class NXGcore(gdb.Command): super().__init__("nxgcore", gdb.COMMAND_USER) + @utils.dont_repeat_decorator def invoke(self, args, from_tty): try: args = parse_args(gdb.string_to_argv(args)) diff --git a/tools/pynuttx/nxgdb/irq.py b/tools/pynuttx/nxgdb/irq.py index 5a36a72efc3..ac51cb49961 100644 --- a/tools/pynuttx/nxgdb/irq.py +++ b/tools/pynuttx/nxgdb/irq.py @@ -64,6 +64,7 @@ class IRQInfoDump(gdb.Command): def __init__(self): super().__init__("irqinfo", gdb.COMMAND_USER) + @utils.dont_repeat_decorator def invoke(self, arg: str, from_tty: bool) -> None: irq_unexpected_isr = utils.gdb_eval_or_none("irq_unexpected_isr") diff --git a/tools/pynuttx/nxgdb/kasan.py b/tools/pynuttx/nxgdb/kasan.py index c45c1571ed0..466a455c961 100644 --- a/tools/pynuttx/nxgdb/kasan.py +++ b/tools/pynuttx/nxgdb/kasan.py @@ -150,6 +150,7 @@ class KASan(gdb.Command): ) ) + @utils.dont_repeat_decorator def invoke(self, args, from_tty): parser = argparse.ArgumentParser( description="Memory Tagging Commands", add_help=False diff --git a/tools/pynuttx/nxgdb/libuv.py b/tools/pynuttx/nxgdb/libuv.py index 77633f7c37e..8aed6b9899d 100644 --- a/tools/pynuttx/nxgdb/libuv.py +++ b/tools/pynuttx/nxgdb/libuv.py @@ -125,6 +125,7 @@ class UVDump(gdb.Command): return None + @utils.dont_repeat_decorator def invoke(self, argument: str, from_tty: bool): parser = argparse.ArgumentParser(description="libuv dump command") parser.add_argument( diff --git a/tools/pynuttx/nxgdb/lists.py b/tools/pynuttx/nxgdb/lists.py index b90bd16d2e8..9d7880ac49e 100644 --- a/tools/pynuttx/nxgdb/lists.py +++ b/tools/pynuttx/nxgdb/lists.py @@ -328,6 +328,7 @@ class ListCheck(gdb.Command): def __init__(self): super().__init__("list_check", gdb.COMMAND_DATA, gdb.COMPLETE_EXPRESSION) + @utils.dont_repeat_decorator def invoke(self, arg, from_tty): argv = gdb.string_to_argv(arg) if len(argv) != 1: @@ -350,6 +351,7 @@ class ForeachListEntry(gdb.Command): def __init__(self): super().__init__("foreach list", gdb.COMMAND_DATA, gdb.COMPLETE_EXPRESSION) + @utils.dont_repeat_decorator def invoke(self, arg, from_tty): argv = gdb.string_to_argv(arg) @@ -407,6 +409,7 @@ class ForeachArray(gdb.Command): def __init__(self): super().__init__("foreach array", gdb.COMMAND_DATA, gdb.COMPLETE_EXPRESSION) + @utils.dont_repeat_decorator def invoke(self, arg, from_tty): argv = gdb.string_to_argv(arg) diff --git a/tools/pynuttx/nxgdb/memcheck.py b/tools/pynuttx/nxgdb/memcheck.py index 4cb1c51d6a4..72444a28da8 100644 --- a/tools/pynuttx/nxgdb/memcheck.py +++ b/tools/pynuttx/nxgdb/memcheck.py @@ -158,6 +158,7 @@ class MMCheck(gdb.Command): f"{len(reasons)} issues @{hex(address)}: " f"{','.join(reasons)}\n" ) + @utils.dont_repeat_decorator def invoke(self, arg: str, from_tty: bool) -> None: try: heaps = memdump.get_heaps() diff --git a/tools/pynuttx/nxgdb/memclassify.py b/tools/pynuttx/nxgdb/memclassify.py index a3a48720ff0..d954bf24898 100644 --- a/tools/pynuttx/nxgdb/memclassify.py +++ b/tools/pynuttx/nxgdb/memclassify.py @@ -315,6 +315,7 @@ class MMClassify(gdb.Command): return args + @utils.dont_repeat_decorator def invoke(self, arg: str, from_tty: bool) -> None: if not (args := self.parse_args(gdb.string_to_argv(arg))): print("memoryclassify: parse args error") diff --git a/tools/pynuttx/nxgdb/memdump.py b/tools/pynuttx/nxgdb/memdump.py index 00cfe1c3af2..07961fd0a51 100644 --- a/tools/pynuttx/nxgdb/memdump.py +++ b/tools/pynuttx/nxgdb/memdump.py @@ -337,6 +337,7 @@ class MMDump(gdb.Command): return nodes + @utils.dont_repeat_decorator def invoke(self, arg: str, from_tty: bool) -> None: if not (args := self.parse_args(arg)): return @@ -434,6 +435,7 @@ class MMfrag(gdb.Command): super().__init__("mm frag", gdb.COMMAND_USER) utils.alias("memfrag", "mm frag") + @utils.dont_repeat_decorator def invoke(self, args, from_tty): parser = argparse.ArgumentParser(description=self.__doc__) parser.add_argument( @@ -521,6 +523,7 @@ class MMMap(gdb.Command): return args + @utils.dont_repeat_decorator def invoke(self, args, from_tty): if not (args := self.parse_arguments(gdb.string_to_argv(args))): return @@ -550,6 +553,7 @@ class MMVisualize(gdb.Command): ) self.pd = utils.import_check("pandas", errmsg="Please pip install pandas\n") + @utils.dont_repeat_decorator def invoke(self, args, from_tty): parser = argparse.ArgumentParser(description=self.__doc__) parser.add_argument( @@ -640,6 +644,7 @@ class MMFree(gdb.Command): super().__init__("mm free", gdb.COMMAND_USER) utils.alias("free", "mm free") + @utils.dont_repeat_decorator def invoke(self, args, from_tty): heaps = mm.get_heaps() @@ -733,6 +738,7 @@ class NxMemoryRange(gdb.Command): super().__init__("mm range", gdb.COMMAND_USER) utils.alias("memrange", "mm range") + @utils.dont_repeat_decorator def invoke(self, arg, from_tty): parser = argparse.ArgumentParser(description=self.__doc__) parser.add_argument("--heap-only", action="store_true", help="Heap only") @@ -764,6 +770,7 @@ class NxDumpRAM(gdb.Command): def __init__(self): super().__init__("dump ram", gdb.COMMAND_USER) + @utils.dont_repeat_decorator def invoke(self, arg: str, from_tty: bool) -> None: parser = argparse.ArgumentParser(description=self.__doc__) parser.add_argument( @@ -811,6 +818,7 @@ class NxMemoryFind(gdb.Command): super().__init__("mm find", gdb.COMMAND_USER) utils.alias("memfind", "mm find") + @utils.dont_repeat_decorator def invoke(self, arg: str, from_tty: bool) -> None: parser = argparse.ArgumentParser(description=self.__doc__) parser.add_argument("pattern", type=str, help="Pattern to search") diff --git a/tools/pynuttx/nxgdb/memleak.py b/tools/pynuttx/nxgdb/memleak.py index 314db6a7c29..61350dfa977 100644 --- a/tools/pynuttx/nxgdb/memleak.py +++ b/tools/pynuttx/nxgdb/memleak.py @@ -184,6 +184,7 @@ class MMLeak(gdb.Command): count = len(nodes[node]) yield node, is_pid_alive(node.pid), count + @utils.dont_repeat_decorator def invoke(self, arg: str, from_tty: bool) -> None: heaps = memdump.get_heaps("g_mmheap") diff --git a/tools/pynuttx/nxgdb/mm.py b/tools/pynuttx/nxgdb/mm.py index ab298ce5c99..1d25eef1f51 100644 --- a/tools/pynuttx/nxgdb/mm.py +++ b/tools/pynuttx/nxgdb/mm.py @@ -758,6 +758,7 @@ class MMHeapInfo(gdb.Command): def __init__(self): super().__init__("mm heap", gdb.COMMAND_USER) + @utils.dont_repeat_decorator def invoke(self, arg: str, from_tty: bool) -> None: for heap in get_heaps(): regions = [(start.address, end.address) for start, end in heap.regions] @@ -773,6 +774,7 @@ class MMPoolInfo(gdb.Command): super().__init__("mm pool", gdb.COMMAND_USER) utils.alias("mempool", "mm pool") + @utils.dont_repeat_decorator def invoke(self, arg: str, from_tty: bool) -> None: parser = argparse.ArgumentParser(description="Dump memory pool information.") parser.add_argument( diff --git a/tools/pynuttx/nxgdb/net.py b/tools/pynuttx/nxgdb/net.py index d0320476822..63e1d0a8750 100644 --- a/tools/pynuttx/nxgdb/net.py +++ b/tools/pynuttx/nxgdb/net.py @@ -237,6 +237,7 @@ class NetStats(gdb.Command): except gdb.error as e: gdb.write("Failed to get UDP stats: %s\n" % e) + @utils.dont_repeat_decorator def invoke(self, args, from_tty): # Parse the arguments in a simple way if not args or "all" in args: @@ -313,6 +314,7 @@ class NetCheck(gdb.Command): finally: return result, message + @utils.dont_repeat_decorator def invoke(self, args, from_tty): if utils.get_symbol_value("CONFIG_MM_IOB"): result, message = self.check_iob() diff --git a/tools/pynuttx/nxgdb/notesnap.py b/tools/pynuttx/nxgdb/notesnap.py index ed38f0c3d5d..a08c7699035 100644 --- a/tools/pynuttx/nxgdb/notesnap.py +++ b/tools/pynuttx/nxgdb/notesnap.py @@ -87,6 +87,7 @@ class NoteSnap(gdb.Command): "message": self.parse_notesnap(), } + @utils.dont_repeat_decorator def invoke(self, args, from_tty): try: print(*(self.parse_notesnap()), sep="\n") diff --git a/tools/pynuttx/nxgdb/nxcrash/busyloop.py b/tools/pynuttx/nxgdb/nxcrash/busyloop.py index aa0e217cb9f..88ed3b4f8a5 100644 --- a/tools/pynuttx/nxgdb/nxcrash/busyloop.py +++ b/tools/pynuttx/nxgdb/nxcrash/busyloop.py @@ -46,6 +46,7 @@ class CrashBusyloop(gdb.Command): return collected + @utils.dont_repeat_decorator def invoke(self, arg: str, from_tty: bool) -> None: collected = self.collect(utils.get_tcbs()) if not collected: diff --git a/tools/pynuttx/nxgdb/nxcrash/deadlock.py b/tools/pynuttx/nxgdb/nxcrash/deadlock.py index ae5463853ea..945fd26b3b8 100644 --- a/tools/pynuttx/nxgdb/nxcrash/deadlock.py +++ b/tools/pynuttx/nxgdb/nxcrash/deadlock.py @@ -81,6 +81,7 @@ class DeadLock(gdb.Command): "deadlocks": {int(pid): [i for i in h] for pid, h in collected}, } + @utils.dont_repeat_decorator def invoke(self, args, from_tty): collected = self.collect(utils.get_tcbs()) if not collected: diff --git a/tools/pynuttx/nxgdb/nxcrash/stackoverflow.py b/tools/pynuttx/nxgdb/nxcrash/stackoverflow.py index eca0a945e1f..97bea4cd3e9 100644 --- a/tools/pynuttx/nxgdb/nxcrash/stackoverflow.py +++ b/tools/pynuttx/nxgdb/nxcrash/stackoverflow.py @@ -55,6 +55,7 @@ class CrashStackOverflow(gdb.Command): return collected + @utils.dont_repeat_decorator def invoke(self, arg: str, from_tty: bool) -> None: collected = self.collect(utils.get_tcbs()) if not collected: diff --git a/tools/pynuttx/nxgdb/nxcrash/thread.py b/tools/pynuttx/nxgdb/nxcrash/thread.py index 4e7a1fcde5f..7bbc3e19cc5 100644 --- a/tools/pynuttx/nxgdb/nxcrash/thread.py +++ b/tools/pynuttx/nxgdb/nxcrash/thread.py @@ -44,6 +44,7 @@ class CrashThread(gdb.Command): return collected or utils.get_running_tcbs() + @utils.dont_repeat_decorator def invoke(self, arg: str, from_tty: bool) -> None: collected = self.collect(utils.get_tcbs()) diff --git a/tools/pynuttx/nxgdb/pginfo.py b/tools/pynuttx/nxgdb/pginfo.py index ad21c55f717..8e6a0734c33 100644 --- a/tools/pynuttx/nxgdb/pginfo.py +++ b/tools/pynuttx/nxgdb/pginfo.py @@ -22,7 +22,7 @@ import gdb -from .utils import read_u64 +from .utils import dont_repeat_decorator, read_u64 class PageTable: @@ -103,6 +103,7 @@ class DumpPageTableCommand(gdb.Command): def __init__(self): super().__init__("dump_pagetable", gdb.COMMAND_USER) + @dont_repeat_decorator def invoke(self, arg, from_tty): arch = gdb.selected_inferior().architecture().name() diff --git a/tools/pynuttx/nxgdb/pm.py b/tools/pynuttx/nxgdb/pm.py index 37ee4220ec3..e8167229e10 100644 --- a/tools/pynuttx/nxgdb/pm.py +++ b/tools/pynuttx/nxgdb/pm.py @@ -90,6 +90,7 @@ class Pmconfig(gdb.Command): + "\n" ) + @utils.dont_repeat_decorator def invoke(self, arg: str, from_tty: bool) -> None: if not has_inferior(): return diff --git a/tools/pynuttx/nxgdb/profile.py b/tools/pynuttx/nxgdb/profile.py index ca80b1e63fa..ea9aa8e016e 100644 --- a/tools/pynuttx/nxgdb/profile.py +++ b/tools/pynuttx/nxgdb/profile.py @@ -22,7 +22,7 @@ import gdb -from .utils import import_check +from .utils import dont_repeat_decorator, import_check class Profile(gdb.Command): @@ -43,6 +43,7 @@ class Profile(gdb.Command): super().__init__("profile", gdb.COMMAND_USER) + @dont_repeat_decorator def invoke(self, args, from_tty): self.cProfile.run(f"gdb.execute('{args}')", "results.prof") @@ -62,6 +63,7 @@ class Time(gdb.Command): def __init__(self): super().__init__("time", gdb.COMMAND_USER) + @dont_repeat_decorator def invoke(self, args, from_tty): import time diff --git a/tools/pynuttx/nxgdb/rpmsg.py b/tools/pynuttx/nxgdb/rpmsg.py index 6eae8a83f41..a6026601709 100644 --- a/tools/pynuttx/nxgdb/rpmsg.py +++ b/tools/pynuttx/nxgdb/rpmsg.py @@ -251,6 +251,7 @@ class RPMsgDump(gdb.Command): self.dump_rpmsg_virtio(rdev) self.dump_rpmsg_port(rdev) + @utils.dont_repeat_decorator def invoke(self, args, from_tty): if not (args := self.parse_args(args)): return diff --git a/tools/pynuttx/nxgdb/stack.py b/tools/pynuttx/nxgdb/stack.py index 04a6d4fe36b..d25e67c2568 100644 --- a/tools/pynuttx/nxgdb/stack.py +++ b/tools/pynuttx/nxgdb/stack.py @@ -200,6 +200,7 @@ class StackUsage(gdb.Command): ) gdb.write("\n") + @utils.dont_repeat_decorator def invoke(self, args, from_tty): stacks = fetch_stacks() diff --git a/tools/pynuttx/nxgdb/target.py b/tools/pynuttx/nxgdb/target.py index f89ec7fd157..0f4df712a21 100644 --- a/tools/pynuttx/nxgdb/target.py +++ b/tools/pynuttx/nxgdb/target.py @@ -36,6 +36,7 @@ class Target(gdb.Command): utils.alias("target nxstub", "target stub") self.process = None + @utils.dont_repeat_decorator def invoke(self, args, from_tty): self.dont_repeat() diff --git a/tools/pynuttx/nxgdb/thread.py b/tools/pynuttx/nxgdb/thread.py index a9a8f828502..cd3a105c386 100644 --- a/tools/pynuttx/nxgdb/thread.py +++ b/tools/pynuttx/nxgdb/thread.py @@ -120,6 +120,7 @@ class RegInfoCommand(gdb.Command): def __init__(self): super().__init__("maintenance reginfo", gdb.COMMAND_USER) + @utils.dont_repeat_decorator def invoke(self, arg: str, from_tty: bool) -> None: registers = g_registers.registers header = ("Name", "Rmt Nr", "Offset", "Tcb Reg Off") @@ -156,6 +157,7 @@ class SetRegs(gdb.Command): def __init__(self): super().__init__("setregs", gdb.COMMAND_USER) + @utils.dont_repeat_decorator def invoke(self, arg, from_tty): parser = argparse.ArgumentParser( description="Set registers to the specified values" @@ -200,6 +202,7 @@ class Nxinfothreads(gdb.Command): def __init__(self): super().__init__("info nxthreads", gdb.COMMAND_USER) + @utils.dont_repeat_decorator def invoke(self, args, from_tty): npidhash = gdb.parse_and_eval("g_npidhash") pidhash = gdb.parse_and_eval("g_pidhash") @@ -284,6 +287,7 @@ class Nxthread(gdb.Command): def __init__(self): super().__init__("nxthread", gdb.COMMAND_USER) + @utils.dont_repeat_decorator def invoke(self, args, from_tty): npidhash = gdb.parse_and_eval("g_npidhash") pidhash = gdb.parse_and_eval("g_pidhash") @@ -368,6 +372,7 @@ class Nxcontinue(gdb.Command): "\n\x1b[31;1m if use thread command, please don't use 'continue', use 'c' instead !!!\x1b[m\n" ) + @utils.dont_repeat_decorator def invoke(self, args, from_tty): g_registers.restore() gdb.execute("continue") @@ -560,6 +565,7 @@ class Ps(gdb.Command): ) gdb.write("\n") + @utils.dont_repeat_decorator def invoke(self, args, from_tty): gdb.write( " ".join( diff --git a/tools/pynuttx/nxgdb/tlsdump.py b/tools/pynuttx/nxgdb/tlsdump.py index 0d2fc811bca..2794f0d8be5 100644 --- a/tools/pynuttx/nxgdb/tlsdump.py +++ b/tools/pynuttx/nxgdb/tlsdump.py @@ -126,6 +126,7 @@ class TlsDump(gdb.Command): print("Error occurred during integrity check") return True + @utils.dont_repeat_decorator def invoke(self, args, from_tty): args = self.parse_arguments(gdb.string_to_argv(args)) if not args: diff --git a/tools/pynuttx/nxgdb/uname.py b/tools/pynuttx/nxgdb/uname.py index 3fe84cb5de9..a9c40ab6839 100644 --- a/tools/pynuttx/nxgdb/uname.py +++ b/tools/pynuttx/nxgdb/uname.py @@ -79,6 +79,7 @@ class UnameCommand(gdb.Command): return args + @utils.dont_repeat_decorator def invoke(self, args, from_tty): args = self.parse_arguments(gdb.string_to_argv(args)) diff --git a/tools/pynuttx/nxgdb/uorb.py b/tools/pynuttx/nxgdb/uorb.py index 3e0c611edbc..29041c2122b 100644 --- a/tools/pynuttx/nxgdb/uorb.py +++ b/tools/pynuttx/nxgdb/uorb.py @@ -127,6 +127,7 @@ class uORBDump(gdb.Command): def __init__(self): super().__init__("uorb", gdb.COMMAND_USER) + @utils.dont_repeat_decorator def invoke(self, arg: str, from_tty: bool) -> None: parser = argparse.ArgumentParser(description=self.__doc__) parser.add_argument( diff --git a/tools/pynuttx/nxgdb/utils.py b/tools/pynuttx/nxgdb/utils.py index 15623e79ad0..9e9e69c3686 100644 --- a/tools/pynuttx/nxgdb/utils.py +++ b/tools/pynuttx/nxgdb/utils.py @@ -335,6 +335,18 @@ def get_field_nitems(t: TypeOrStr, field: str) -> Union[int, None]: long_type = lookup_type("long") + +def dont_repeat_decorator(func): + def wrapper(self, args, from_tty): + try: + self.dont_repeat() + func(self, args, from_tty) + except Exception as e: + print(f"Error: {e}") + + return wrapper + + # Common Helper Functions @@ -1175,6 +1187,7 @@ class Hexdump(gdb.Command): def __init__(self): super().__init__("hexdump", gdb.COMMAND_USER) + @dont_repeat_decorator def invoke(self, args, from_tty): argv = args.split(" ") address = 0 @@ -1221,6 +1234,7 @@ class Addr2Line(gdb.Command): backtraces = Backtrace(addresses, formatter=self.formatter, break_null=False) gdb.write(str(backtraces)) + @dont_repeat_decorator def invoke(self, args, from_tty): if not args: gdb.write(Addr2Line.__doc__ + "\n") diff --git a/tools/pynuttx/nxgdb/wdog.py b/tools/pynuttx/nxgdb/wdog.py index bd248f82745..56c43ad786b 100644 --- a/tools/pynuttx/nxgdb/wdog.py +++ b/tools/pynuttx/nxgdb/wdog.py @@ -62,6 +62,7 @@ class WDogDump(gdb.Command): def __init__(self): super().__init__("wdog", gdb.COMMAND_USER) + @utils.dont_repeat_decorator def invoke(self, arg, from_tty): for wdog in get_wdog_list(): print(wdog) diff --git a/tools/pynuttx/nxgdb/wqueue.py b/tools/pynuttx/nxgdb/wqueue.py index 9e4f60d74da..4f85389a9b3 100644 --- a/tools/pynuttx/nxgdb/wqueue.py +++ b/tools/pynuttx/nxgdb/wqueue.py @@ -155,6 +155,7 @@ class WorkQueueDump(gdb.Command): super().__init__("worker", gdb.COMMAND_USER) + @utils.dont_repeat_decorator def invoke(self, arg, from_tty): queues = get_work_queues() for queue in queues: -- Gitee From 00852746436252e03af0020cfbae82bcea56219f Mon Sep 17 00:00:00 2001 From: xuxingliang Date: Wed, 9 Apr 2025 09:52:27 +0800 Subject: [PATCH 175/235] nxstub: always use tcb.xcp.regs to fetch registers VELAPLATFO-57759 When system crashes, the running task's register is saved to g_last_regs array. But on rare cases, the task state is wrong, thus causing nxstub to return wrong register. Now we unify the behavior of nxstub, that user need to manually use command 'monitor setregs g_last_regs' to switch registers value, nxstub will always use tcb.xcp.regs by default. If GDB plugin is loaded, the python command 'setregs' can be used directly. E.g. 'setregs g_last_regs'. This patch fixes the GDB plugin command 'crash thread' that reports wrong thread crashed because of the wrong registers. Change-Id: I950f321eb71b8800ec54a94a2f0d38599ace41e5 Signed-off-by: xuxingliang --- tools/pynuttx/nxstub/target.py | 45 +++++++++++++++++++--------------- 1 file changed, 25 insertions(+), 20 deletions(-) diff --git a/tools/pynuttx/nxstub/target.py b/tools/pynuttx/nxstub/target.py index 061732c9abb..9201f536a1b 100644 --- a/tools/pynuttx/nxstub/target.py +++ b/tools/pynuttx/nxstub/target.py @@ -137,7 +137,6 @@ class Target: return self.threads ncpus = utils.get_ncpus(self.elf) - regsize = utils.get_regsize(self.elf) data, sym = self._read_symbol("g_running_tasks") # an array of pointers running_tasks = utils.parse_array(data, pointer, ncpus) @@ -162,16 +161,8 @@ class Target: state = utils.uint8_t(data[tcbinfo.state_off : tcbinfo.state_off + 1]) state = states[state] if state < len(states) else "Unknown" - if address in running_tasks: - # Running task registers is not in memory, best chance is the registers - # stored in g_last_regs when assert happened. - last_regs = self.elf.get_symbol("g_last_regs").value - cpu = running_tasks.index(address) - xcpregs = cpu * regsize + last_regs - else: - off = tcbinfo.regs_off - xcpregs = data[off : off + pointer.sizeof()] - xcpregs = pointer.parse(xcpregs) + xcpregs = data[tcbinfo.regs_off : tcbinfo.regs_off + pointer.sizeof()] + xcpregs = pointer.parse(xcpregs) try: registers.load(addr=xcpregs) @@ -290,15 +281,29 @@ class Target: if command.startswith(b"setregs"): command = command.decode("ascii") _, address = command.split(" ") - try: - address = ( - int(address, 16) - if "0x" in address or "0X" in address - else int(address) - ) - except ValueError: - # try if it's a symbol, note that expression is not supported. - address = self.elf.get_symbol(address).value + + # Check frequently used symbols + if address.startswith("g_last_regs"): + # address could be g_last_regs or g_last_regs[1] or g_last_regs[0] etc. + if "[" in address: + regsize = utils.get_regsize(self.elf) + splitted = address.split("[") + index = int(splitted[1].split("]")[0]) + address = self.elf.get_symbol(splitted[0]).value + address += index * regsize + else: + symbol = self.elf.get_symbol(address) + address = symbol.value + else: + try: + address = ( + int(address, 16) + if "0x" in address or "0X" in address + else int(address) + ) + except ValueError: + # try if it's a symbol, note that expression is not supported. + address = self.elf.get_symbol(address).value self.registers.load(address) return f"Loaded registers from {address:#x}\n" -- Gitee From 5d0e6628796abffecb82696f66201de0392cfa2b Mon Sep 17 00:00:00 2001 From: xuxingliang Date: Thu, 10 Apr 2025 11:51:56 +0800 Subject: [PATCH 176/235] nxgdb/utils: ignore modules that failed to import VELAPLATFO-57847 Change-Id: Ifee7a58a14b1a41225e3dca042edf0f28c9c95ab Signed-off-by: xuxingliang --- tools/pynuttx/nxgdb/utils.py | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/tools/pynuttx/nxgdb/utils.py b/tools/pynuttx/nxgdb/utils.py index 9e9e69c3686..995aba6be00 100644 --- a/tools/pynuttx/nxgdb/utils.py +++ b/tools/pynuttx/nxgdb/utils.py @@ -1068,10 +1068,13 @@ def gather_gdbcommands(modules=None, path=None) -> List[gdb.Command]: modules = modules or gather_modules(path) commands = [] for m in modules: - module = importlib.import_module(f"{__package__}.{m}") - for c in module.__dict__.values(): - if isinstance(c, type) and issubclass(c, gdb.Command): - commands.append(c) + try: + module = importlib.import_module(f"{__package__}.{m}") + for c in module.__dict__.values(): + if isinstance(c, type) and issubclass(c, gdb.Command): + commands.append(c) + except Exception: + gdb.write(f"Ignore module {m}\n") return commands -- Gitee From 666912089bf9d9cb351f68ff84793d059323e879 Mon Sep 17 00:00:00 2001 From: xuxingliang Date: Wed, 16 Apr 2025 11:16:07 +0800 Subject: [PATCH 177/235] nxstub: fix overlapped memory write VELAPLATFO-58517 1. Should use length of data to write to calculate offset. 2. Should break the loop after new memory written. Change-Id: Ia85728fab565c3a8b0668ec214f8370842688ddb Signed-off-by: xuxingliang --- tools/pynuttx/nxstub/target.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/tools/pynuttx/nxstub/target.py b/tools/pynuttx/nxstub/target.py index 9201f536a1b..5aa18f5939a 100644 --- a/tools/pynuttx/nxstub/target.py +++ b/tools/pynuttx/nxstub/target.py @@ -255,14 +255,12 @@ class Target: if address + len(data) < m.address: memories.insert(i, mem) # New memory region in the middle - return - - if (offset := address - m.address) >= 0: + elif (offset := address - m.address) >= 0: # Overwrite and append data to existing memory m.data[offset : offset + len(data)] = data else: # Prepend data to existing memory - offset = address + len(m) - m.address + offset = address + len(data) - m.address m.data = data + m.data[offset:] m.address = address @@ -275,6 +273,8 @@ class Target: memories.remove(m2) m.data += m2.data[end - m2.address :] + break + def monitor_command(self, command: bytes) -> str: """Handle monitor command""" self.logger.debug(f"Monitor command: {command}") -- Gitee From e5b3539161e3d7561bc5615c147fa40627c38657 Mon Sep 17 00:00:00 2001 From: xuxingliang Date: Thu, 10 Apr 2025 10:29:45 +0800 Subject: [PATCH 178/235] nxstub: support to use memory dump directory as input. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit VELAPLATFO-56229 The directly should includes memory dump files named as address.bin, where address should be in hex number. E.g $ tree memdump memdump ├── 0x70000000.bin ├── 0x70004000.bin ├── 0x70021400.bin ├── 0x70021578.bin ├── 0x70030e00.bin ├── 0x70031300.bin ├── 0x70031c00.bin ├── 0x80040100.bin ├── 0x800d2a30.bin ├── 0x90000000.bin ├── 0xb0400000.bin └── 0xb04c0000.bin 0 directories, 12 files Usage: ./nuttx/tools/gdbserver.py -a tricore -r memdump -e nuttx Note: In GDB plugin command, we added `dump ram` that can automatically dump all memory to a directory. It can be loaded to gdbserver directly using above method. Change-Id: I390a21eba37cd7a28f175b200fb1eb19089ede49 Signed-off-by: xuxingliang --- tools/pynuttx/nxstub/__init__.py | 42 ++++++++++++++++++++++++++------ 1 file changed, 34 insertions(+), 8 deletions(-) diff --git a/tools/pynuttx/nxstub/__init__.py b/tools/pynuttx/nxstub/__init__.py index 09e7b17f69b..9184634a332 100644 --- a/tools/pynuttx/nxstub/__init__.py +++ b/tools/pynuttx/nxstub/__init__.py @@ -23,6 +23,7 @@ __version__ = "0.0.1" import argparse import logging import multiprocessing +import os import re import signal import subprocess @@ -123,12 +124,38 @@ def gdbstub_start(args): memories = [] registers = None - for rawfile in args.rawfile or []: - filename, address = rawfile.split(":") - address = int(address, 16) - with open(filename, "rb") as f: - memories.append(RawMemory(address, f.read())) - print(f"Add memory dump: {memories[-1]}") + for name in args.rawfile or []: + + def get_address(filename: str): + """ + Get memory dump address from file name from below formats + memdump.bin:0x123456 + abc/0x123456.bin + 0x123456.bin + abc/123456.bin + 123456.bin + """ + try: + if ":" in filename: + return int(filename.split(":")[1], 16) + else: + return int(filename.split("/")[-1].split(".")[0], 0) + except ValueError: + return None + + if os.path.isdir(name): + for f in os.listdir(name): + if (address := get_address(f)) is None: + print(f"Ignore file {os.path.join(name, f)}") + else: + with open(os.path.join(name, f), "rb") as f: + memories.append(RawMemory(address, f.read())) + print(f"Add memory dump: {memories[-1]}") + else: + address = get_address(name) + with open(name, "rb") as f: + memories.append(RawMemory(address, f.read())) + print(f"Add memory dump: {memories[-1]}") elf = utils.LiefELF(args.elffile) registers, mem = parse_log(elf, args.arch, args.log) @@ -254,8 +281,6 @@ def parse_args(args=None): def main(args=None): args = parse_args(args) - - gdb = None if args.debug: logging.basicConfig( format="%(asctime)s:%(levelname)s:%(name)s:%(message)s", @@ -263,6 +288,7 @@ def main(args=None): logging.getLogger(__name__).setLevel(logging.DEBUG) logging.getLogger("nxreg").setLevel(logging.DEBUG) + gdb = None if args.gdb: gdb = gdb_start(args) # Ignore the Ctrl+C signal -- Gitee From 59409dab5154728c43f6604221ef5ad2ae4e7432 Mon Sep 17 00:00:00 2001 From: wangshaoxin Date: Mon, 14 Apr 2025 16:30:22 +0800 Subject: [PATCH 179/235] nxgdb/rpmsg.py: solve dump_rpmsg_port_buffer error VELAPLATFO-58277 1. rpmsg_port_node_to_buf function error parse 2. hdr was not converted, identification error 3. rdev is directly forced to convert to rpmsg_port_s. Error, parsing failed Change-Id: Ie9c6243710246757cebea3ac37aac4f7e7d11f0f Signed-off-by: wangshaoxin --- tools/pynuttx/nxgdb/rpmsg.py | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/tools/pynuttx/nxgdb/rpmsg.py b/tools/pynuttx/nxgdb/rpmsg.py index a6026601709..e9aaf81c1db 100644 --- a/tools/pynuttx/nxgdb/rpmsg.py +++ b/tools/pynuttx/nxgdb/rpmsg.py @@ -149,8 +149,10 @@ class RPMsgDump(gdb.Command): return None def rpmsg_port_node_to_buf(self, queue, node): - node_offset = int(node) - int(queue["node"]) - buf_addr = queue["buf"] + (node_offset * queue["len"]) + node_offset = (int(node) - int(queue["node"])) / int( + utils.sizeof("struct list_node") + ) + buf_addr = queue["buf"] + (int(node_offset) * queue["len"]) return buf_addr def dump_rpmsg_port_buffer(self, rdev, queue, label): @@ -159,6 +161,7 @@ class RPMsgDump(gdb.Command): for node in NxList(head): hdr = self.rpmsg_port_node_to_buf(queue, node) + hdr = hdr.cast(utils.lookup_type("struct rpmsg_port_header_s").pointer()) if not hdr or not hdr["buf"]: continue @@ -175,7 +178,7 @@ class RPMsgDump(gdb.Command): if not self.is_rpmsg_transport(rdev, "port"): return - port = rdev.cast(utils.lookup_type("struct rpmsg_port_s").pointer()) + port = utils.container_of(rdev, "struct rpmsg_port_s", "rdev") gdb.write(f"rxq nused:{port['rxq']['ready']['num']}\n") gdb.write(f"rxq navail:{port['rxq']['free']['num']}\n") -- Gitee From 527de00776d629c0770f437d1b73a22e621c49ff Mon Sep 17 00:00:00 2001 From: xuxingliang Date: Thu, 10 Apr 2025 13:55:55 +0800 Subject: [PATCH 180/235] nxstub: fix memory write command VELAPLATFO-56229 Change-Id: If77b027475c9e28064859ccb6da3293f0cdb0aa8 Signed-off-by: xuxingliang --- tools/pynuttx/nxstub/gdbstub.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/tools/pynuttx/nxstub/gdbstub.py b/tools/pynuttx/nxstub/gdbstub.py index 976571e35bf..0bf5f76fc91 100644 --- a/tools/pynuttx/nxstub/gdbstub.py +++ b/tools/pynuttx/nxstub/gdbstub.py @@ -239,7 +239,11 @@ class GDBStub: packet = packet.decode("ascii") addr, length_and_data = packet[1:].split(",") length, data = length_and_data.split(":") - ok = self.target.memory_write(int(addr, 16), unhexlify(data), int(length, 16)) + if int(length, 16) != len(data) // 2: + self.send_packet("E01") + return + + ok = self.target.memory_write(int(addr, 16), unhexlify(data)) self.send_packet("OK" if ok else "") def handle_etx(self, packet: bytes): -- Gitee From 468849b1f50fba02341423b1a096697def016e7b Mon Sep 17 00:00:00 2001 From: xuxingliang Date: Tue, 15 Apr 2025 17:37:13 +0800 Subject: [PATCH 181/235] nxstub: automatically identify the dump file/directory type VELAPLATFO-56229 Add optional positional argument 'dump' that could be crash log, coredump, memory dump directory or memory dump file in format of 0x12345678.bin. E.g. gdbserver.py -a arm -e nuttx coredump.core gdbserver.py -a arm -e nuttx 0x12345678.bin gdbserver.py -a arm -e nuttx path/to/memorydump gdbserver.py -a arm -e nuttx crash.log Change-Id: I0626a47b62391981d200ccf90e54d5d5b01446de Signed-off-by: xuxingliang --- tools/pynuttx/nxstub/__init__.py | 56 +++++++++++++++++++++++++++++++- 1 file changed, 55 insertions(+), 1 deletion(-) diff --git a/tools/pynuttx/nxstub/__init__.py b/tools/pynuttx/nxstub/__init__.py index 9184634a332..73a08b22b9d 100644 --- a/tools/pynuttx/nxstub/__init__.py +++ b/tools/pynuttx/nxstub/__init__.py @@ -120,10 +120,56 @@ def parse_log(elf, arch, logfile): return registers[int(choice)], memories[int(choice)] +def auto_parse_dump(args): + """ + Automatically parse the dump file, which could be a crash log, memory dump or core dump. + Store the parsed result directly to args, so the remaining logic keeps unchanged. + """ + dump = args.dump + if not dump: + return + + if args.rawfile or args.log or args.core: + raise ValueError("Error: 'dump' cannot be used with rawfile, log, or core.") + + if os.path.isdir(dump): + # We suppose only memory dump could be a directory + print(f"Input is raw memory dump: {dump}") + args.rawfile = [dump] # rawfile must be a list + return + + def is_core_file(file): + # check elf header, check magic and elf type is CORE + with open(dump, "rb") as f: + magic = f.read(4) + if magic != b"\x7fELF": + return False + + f.seek(0x10) + elf_type = int.from_bytes(f.read(2), "little") + return elf_type == 4 + + # Check if the dump file is a crash log, memory dump or core dump + if dump.endswith(".log"): + print(f"Input is crash log: {dump}") + args.log = dump + elif dump.endswith(".bin"): + print(f"Input is raw memory dump: {dump}") + args.rawfile = dump + elif is_core_file(dump): + print(f"Input is core dump: {dump}") + args.core = dump + else: + raise ValueError(f"Unknown dump file type: {dump}") + + def gdbstub_start(args): memories = [] registers = None + # Parse args.dump to normal parameter if exist + auto_parse_dump(args) + for name in args.rawfile or []: def get_address(filename: str): @@ -275,6 +321,13 @@ def parse_args(args=None): type=str, help=f'Optional custom GDB init command when GDB launches, default: "{DEFAULT_GDB_INIT_CMD}".', ) + parser.add_argument( + "dump", + type=str, + nargs="?", + default=None, + help="Optional dump file that could be crash log, memory dump or core dump, automatically parsed.", + ) return parser.parse_args(args) @@ -297,8 +350,9 @@ def main(args=None): try: gdbstub_start(args) except Exception as e: - print(f"GDBStub error: {e}:\n {traceback.format_exc()}") + print(f"GDBStub error: {e}\n {traceback.format_exc() if args.debug else ''}") if gdb: + print("Stop GDB session...") gdb.kill() gdb.join() -- Gitee From 4b88d9f233d4d509a6f468d85b07266fa5d3c53f Mon Sep 17 00:00:00 2001 From: yangao1 Date: Mon, 21 Apr 2025 19:16:08 +0800 Subject: [PATCH 182/235] nxstub/target.py:add readmem member for registers class VELAPLATFO-58844 Change-Id: I5be58aa216a2584b1aff5c9e21f627a643db8bc7 Signed-off-by: yangao1 --- tools/pynuttx/nxstub/target.py | 1 + 1 file changed, 1 insertion(+) diff --git a/tools/pynuttx/nxstub/target.py b/tools/pynuttx/nxstub/target.py index 5aa18f5939a..a21f59511b6 100644 --- a/tools/pynuttx/nxstub/target.py +++ b/tools/pynuttx/nxstub/target.py @@ -84,6 +84,7 @@ class Target: self.core: utils.LiefELF = core self.registers = registers or Registers(elf, arch=arch) self.memories: List[RawMemory] = [] + self.registers.readmem = self.memory_read self.arch = arch self.pid = self.PID0_REPLACE # Current thread PID self.remap = remap or [] -- Gitee From 7b0ca0c89b29ff474c83532b1b8d72b59a0013db Mon Sep 17 00:00:00 2001 From: wangmingrong1 Date: Mon, 14 Apr 2025 15:15:14 +0800 Subject: [PATCH 183/235] gdb plugin: Add string printing after loading is completed VELAPLATFO-57940 Used to test that the matching script is loaded Change-Id: Ief79b9ad7d7a5179d1c228780e3e434a3fc29984 Signed-off-by: wangmingrong1 (cherry picked from commit 85b85b2686d67965eeb15ddd5ccfc5dfa1f44292) --- tools/pynuttx/gdbinit.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tools/pynuttx/gdbinit.py b/tools/pynuttx/gdbinit.py index 440acb89baf..954ab513dd5 100644 --- a/tools/pynuttx/gdbinit.py +++ b/tools/pynuttx/gdbinit.py @@ -35,3 +35,5 @@ if __name__ == "__main__": del sys.modules[key] import nxgdb # noqa: F401 + + print("GDB Plugin Loaded Successfully") -- Gitee From 05eca28185997aaa7d35d48c4fb95910a19f6c4e Mon Sep 17 00:00:00 2001 From: wangmingrong1 Date: Wed, 9 Apr 2025 12:30:16 +0800 Subject: [PATCH 184/235] GDB Plugin test:Load the library of the current virtual environment before starting GDB VELAPLATFO-57940 Prepare the environment for gdb plugin testing in a virtual environment. However, this requires that the Python version in the virtual environment should be as consistent as possible with the Python version in the real environment. Change-Id: I04defbbdef076e6d1cb50ee753600a12450d8fc5 Signed-off-by: wangmingrong1 (cherry picked from commit 28886595bb28129751dc493896a73e298e0cb7b2) --- tools/pynuttx/tests/run_tests.sh | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/tools/pynuttx/tests/run_tests.sh b/tools/pynuttx/tests/run_tests.sh index d3819515aa2..3acfae61e17 100755 --- a/tools/pynuttx/tests/run_tests.sh +++ b/tools/pynuttx/tests/run_tests.sh @@ -133,6 +133,10 @@ python -c "import sys; print(sys.version); print(sys.path)" echo "##############################" +# Prepare the environment for gdb plugin testing in a virtual environment. However, +# this requires that the Python version in the virtual environment +# should be as consistent as possible with the Python version in the real environment. +PACKAGE_PATH=$(python -m site | grep 'site-packages' | head -n 1 | sed 's/^[ \t]*//;s/[ \t]*$//') # Test requires running the ELF without Qemu gdb-multiarch \ @@ -142,7 +146,7 @@ ${elffile} \ -ex="b up_idle" \ -ex="${EXTRA_CMD}" \ -ex="c" \ --ex="python import sys; print(sys.version); print(sys.executable); print(sys.path)" \ +-ex="python import sys; sys.path.append(${PACKAGE_PATH}); print(sys.version); print(sys.executable); print(sys.path)" \ -ex="source ${GDB_TOOLS}/gdbinit.py" \ -ex="source ${GDB_TOOLS}/tests/runner.py" \ -- Gitee From b420a6eefa522fe6355288d4ee35949f818637a9 Mon Sep 17 00:00:00 2001 From: wangmingrong1 Date: Tue, 15 Apr 2025 12:04:44 +0800 Subject: [PATCH 185/235] gdb plugin test: Delete redundant scripts VELAPLATFO-57940 Delete the redundant scripts, directly source tests/runner.py and breakpoint operations on the test framework Change-Id: Ibe751de9b06af5cdc826923a421ae58b800877d7 Signed-off-by: wangmingrong1 (cherry picked from commit 272399e532214deb5814ef791c80eacd2dba6172) --- tools/pynuttx/tests/run_tests.sh | 174 ------------------------------- tools/pynuttx/tests/runner.py | 5 +- 2 files changed, 2 insertions(+), 177 deletions(-) delete mode 100755 tools/pynuttx/tests/run_tests.sh diff --git a/tools/pynuttx/tests/run_tests.sh b/tools/pynuttx/tests/run_tests.sh deleted file mode 100755 index 3acfae61e17..00000000000 --- a/tools/pynuttx/tests/run_tests.sh +++ /dev/null @@ -1,174 +0,0 @@ -#! /bin/bash -############################################################################ -# tools/pynuttx/tests/run_tests.sh -# -# Licensed to the Apache Software Foundation (ASF) under one or more -# contributor license agreements. See the NOTICE file distributed with -# this work for additional information regarding copyright ownership. The -# ASF licenses this file to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance with the -# License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# -############################################################################ - -set -xeo pipefail - -GDB_TOOLS=$(dirname $0)/../ -NUTTX_EXE=$(dirname $0)/../../../nuttx - -# The default target -elffile=${NUTTX_EXE} -use_qemu=true - -qemu_gdb_srv_pid= - -GDB_SOCKET_NAME= - -# Pls uncomment this for local testing - -# start_qemu_gdb_srv() -# { -# qemu-system-arm \ -# -M mps3-an547 \ -# -nographic \ -# -kernel ${elffile} \ -# -chardev socket,path=$GDB_SOCKET_NAME,server=on,wait=off,id=gdb0 \ -# -gdb chardev:gdb0 \ -# -S & 1>/dev/null 2>&1 - -# qemu_gdb_srv_pid=$! - -# if ! ps -p $qemu_gdb_srv_pid > /dev/null; then -# echo "Failed to start qemu due to: $?" -# exit 1 -# fi - -# while [ ! -e "$GDB_SOCKET_NAME" ] -# do -# echo "Waiting for $GDB_SOCKET_NAME to exist..." -# sleep 0.5 # Wait for 0.5 second before checking again -# done -# } - -usage() { - echo "USAGE: ${0} [options]" - echo "" - echo "Options:" - echo "-h" - echo "-e the target ELF file, an absolute path should be given. By default, we will look for one in nuttx/" - echo "-t path to the gdb scritps, by default we will look for the relative path to nuttx/tools/gdb" - echo "-s if the target ELF is the nuttx simulator" - echo "-c the socket to connect to" - - exit $@ -} - -while [ ! -z "$1" ]; do - case "$1" in - -h ) - usage 0 - ;; - -e ) - shift - elffile=$1 - ;; - -t ) - shift - GDB_TOOLS=$1 - ;; - -s ) - use_qemu= - ;; - -c ) - shift - GDB_SOCKET_NAME=$1 - ;; - * ) - break - ;; - esac - shift -done - -if ! [ -f ${elffile} ]; then - echo "Failed to find the target ELF file" - exit 1 -fi - -if ! [ -d ${GDB_TOOLS} ]; then - echo "The required GDB tools not exist" - exit 1 -fi - -EXTRA_CMD= -if [ -z "$use_qemu" ]; then - EXTRA_CMD="r" -else - EXTRA_CMD="target remote $GDB_SOCKET_NAME" -fi - -if ! [ -z "$use_qemu" ]; then - # Pls uncomment this for local testing - # start_qemu_gdb_srv - echo "Using the qemu as the testing platform" -fi - -echo "##############################" -# figure out where we are running at? - -echo `whoami` -echo `id` -echo `ifconfig` -echo `which python` -echo $(realpath `which python`) -python -c "import sys; print(sys.version); print(sys.path)" - -echo "##############################" - -# Prepare the environment for gdb plugin testing in a virtual environment. However, -# this requires that the Python version in the virtual environment -# should be as consistent as possible with the Python version in the real environment. -PACKAGE_PATH=$(python -m site | grep 'site-packages' | head -n 1 | sed 's/^[ \t]*//;s/[ \t]*$//') - -# Test requires running the ELF without Qemu -gdb-multiarch \ --batch \ -${elffile} \ --return-child-result \ --ex="b up_idle" \ --ex="${EXTRA_CMD}" \ --ex="c" \ --ex="python import sys; sys.path.append(${PACKAGE_PATH}); print(sys.version); print(sys.executable); print(sys.path)" \ --ex="source ${GDB_TOOLS}/gdbinit.py" \ --ex="source ${GDB_TOOLS}/tests/runner.py" \ - -result=$? - -# Don't fail with an error code, all we need is -# to proceed Qemu without letting it hang. -# A bit tricky here, we attach the gdb again -# and quit -yes | gdb-multiarch \ --batch \ -${elffile} \ --ex="${EXTRA_CMD}" \ --ex="q" || true - -# After everything is done, don't bother just kill the Qemu process -if ! [ -z $qemu_gdb_srv_pid ]; then - kill -9 $qemu_gdb_srv_pid -fi - -if [ -f $GDB_SOCKET_NAME ]; then - unlink $GDB_SOCKET_NAME -fi - -exit $result diff --git a/tools/pynuttx/tests/runner.py b/tools/pynuttx/tests/runner.py index e5c950c3bf0..7403e247697 100755 --- a/tools/pynuttx/tests/runner.py +++ b/tools/pynuttx/tests/runner.py @@ -20,7 +20,6 @@ ############################################################################ import os -import sys import unittest if __name__ == "__main__": @@ -40,6 +39,6 @@ if __name__ == "__main__": result_mock = test_runner.run(testsuit_mock) if not result_runtime.wasSuccessful() or not result_mock.wasSuccessful(): - sys.exit(255) + print("GDB Plugin Test Failed") else: - sys.exit(0) + print("GDB Plugin Test Successfully") -- Gitee From 2621f4ee4ad1159418f623f6ea8d5dc3575cd046 Mon Sep 17 00:00:00 2001 From: ganjing Date: Tue, 8 Apr 2025 18:54:31 +0800 Subject: [PATCH 186/235] improvement: check if the GDB Plugin is registered VELAPLATFO-57820 Change-Id: I6397e41e60510860f9e33ba38178a4290482d2ce Signed-off-by: ganjing --- tools/pynuttx/nxgdb/diagnose.py | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/tools/pynuttx/nxgdb/diagnose.py b/tools/pynuttx/nxgdb/diagnose.py index cd53941ced6..54391550a85 100644 --- a/tools/pynuttx/nxgdb/diagnose.py +++ b/tools/pynuttx/nxgdb/diagnose.py @@ -21,6 +21,7 @@ ############################################################################ import argparse +from gc import get_referrers import gdb @@ -66,11 +67,20 @@ class DiagnoseReport(gdb.Command): commands = utils.gather_gdbcommands(modules=modules) + registered_command_types = { + obj.__class__.__name__.lower() + for cls in gdb.Command.__subclasses__() + for obj in get_referrers(cls) + if isinstance(obj, cls) and not isinstance(obj, type) + } + results = [] for clz in commands: if hasattr(clz, "diagnose"): command = clz() name = clz.__name__.lower() + if name not in registered_command_types: + continue gdb.write(f"Run command: {name}\n") try: result = command.diagnose() -- Gitee From bcab4dd331872fdfb6fd0dc1b2c25e59cb35d274 Mon Sep 17 00:00:00 2001 From: ganjing Date: Fri, 18 Apr 2025 09:55:28 +0800 Subject: [PATCH 187/235] fix: modify the format of the notesnap tool's diagnose report to info VELAPLATFO-58692 Change-Id: Ie241840917c03c70f5f945b9423059dad6cdc916 Signed-off-by: ganjing --- tools/pynuttx/nxgdb/notesnap.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/pynuttx/nxgdb/notesnap.py b/tools/pynuttx/nxgdb/notesnap.py index a08c7699035..8674f050568 100644 --- a/tools/pynuttx/nxgdb/notesnap.py +++ b/tools/pynuttx/nxgdb/notesnap.py @@ -83,7 +83,7 @@ class NoteSnap(gdb.Command): "title": "Notesnap Report", "summary": "notesnap dump", "command": "notesnap", - "result": "pass", + "result": "info", "message": self.parse_notesnap(), } -- Gitee From a44e9f1330dabbbe1197dafb2ce50dab3fbb0d72 Mon Sep 17 00:00:00 2001 From: xuxingliang Date: Wed, 23 Apr 2025 19:56:44 +0800 Subject: [PATCH 188/235] nxgdb: fix style issue VELAPLATFO-58808 Fix style issue reported after upgrading flake8 to 7.2.0 1 file would be left unchanged. /home/neo/pool/o61/nuttx/tools/pynuttx/nxgdb/utils.py:237:5: F824 is unused: name is never assigned in scope global g_type_cache ^ /home/neo/pool/o61/nuttx/tools/pynuttx/nxgdb/utils.py:294:5: F824 is unused: name is never assigned in scope global long_type ^ Change-Id: I32750ff15ccf409d007b74f08a91494cc902b51c Signed-off-by: xuxingliang --- tools/pynuttx/nxgdb/utils.py | 3 --- 1 file changed, 3 deletions(-) diff --git a/tools/pynuttx/nxgdb/utils.py b/tools/pynuttx/nxgdb/utils.py index 995aba6be00..9eebe08cb1a 100644 --- a/tools/pynuttx/nxgdb/utils.py +++ b/tools/pynuttx/nxgdb/utils.py @@ -280,8 +280,6 @@ class Backtrace: def lookup_type(name, block=None) -> gdb.Type: """Return the type object of a type name""" - global g_type_cache - key = (name, block) if key not in g_type_cache: try: @@ -352,7 +350,6 @@ def dont_repeat_decorator(func): def get_long_type(): """Return the cached long type object""" - global long_type return long_type -- Gitee From 2a7a1d77aa5bef9e08a674f6ca947e996929e34f Mon Sep 17 00:00:00 2001 From: xuxingliang Date: Wed, 9 Apr 2025 10:47:12 +0800 Subject: [PATCH 189/235] nxgdb/crash: analysis if crash happened in g_last_regs VELAPLATFO-57759 If setregs command is supported, aka GDB has a process to debug, we check backtrace of g_last_regs to see if crash happend. If so, it's highly likely g_running_tasks has crashed, append the task name and pid etc if tcb is valid. Note that it could report wrong thread name because of the wrong task state. Optimize the command output by adding crash thread backtrace. E.g. (gdb) crash thread Found 1 crashed threads PID Name 0 g_last_regs[0]-Idle_Task <_assert+698> <__assert+44> (gdb) Note that Idle is running, thus it reports Idle has crashed. But though the backtrace we can see it's actually kvdbd. (gdb) t 1 [Switching to thread 1.1 (Thread 2147483647)] #0 0x0067e51c in up_idle () at /home/work/ssd1/workspace/MiRTOS-qemu-miwear-trunk-25rc01-Build/nuttx/arch/arm/src/goldfish/goldfish_idle.c:81 81 /home/work/ssd1/workspace/MiRTOS-qemu-miwear-trunk-25rc01-Build/nuttx/arch/arm/src/goldfish/goldfish_idle.c: No such file or directory. (gdb) bt #0 0x0067e51c in up_idle () at /home/work/ssd1/workspace/MiRTOS-qemu-miwear-trunk-25rc01-Build/nuttx/arch/arm/src/goldfish/goldfish_idle.c:81 #1 0x0065fe16 in nx_start () at /home/work/ssd1/workspace/MiRTOS-qemu-miwear-trunk-25rc01-Build/nuttx/sched/init/nx_start.c:786 #2 0x00000000 in ?? () (gdb) Change-Id: I86434ceb61f4d9899c319587874f6f6680ab3310 Signed-off-by: xuxingliang --- tools/pynuttx/nxgdb/nxcrash/thread.py | 92 ++++++++++++++++++++++----- 1 file changed, 76 insertions(+), 16 deletions(-) diff --git a/tools/pynuttx/nxgdb/nxcrash/thread.py b/tools/pynuttx/nxgdb/nxcrash/thread.py index 7bbc3e19cc5..a2dd468eed0 100644 --- a/tools/pynuttx/nxgdb/nxcrash/thread.py +++ b/tools/pynuttx/nxgdb/nxcrash/thread.py @@ -20,29 +20,79 @@ # ############################################################################ +from dataclasses import dataclass +from typing import List + import gdb from .. import utils +@dataclass +class ThreadInfo: + """Thread information""" + + pid: int + name: str + backtrace: utils.Backtrace + crashed: bool = False + + class CrashThread(gdb.Command): """Analyse and collect the crashed threads""" def __init__(self): super().__init__("crash thread", gdb.COMMAND_USER) - def collect(self, tcbs): + def collect(self, tcbs) -> List[ThreadInfo]: """Collect threads that crashed information""" + def is_thread_crashed(pid): + """Check if the thread is crashed""" + # Check if the thread is in the crashed state + for frame in utils.get_thread_frames(pid): + if "_assert" in utils.get_frame_func_name(frame): + return True + + def get_thread_info(tcb): + pid = int(tcb.pid) + return ThreadInfo( + pid=pid, + name=utils.get_task_name(tcb), + backtrace=utils.Backtrace(utils.get_backtrace(pid)), + crashed=True, + ) + collected = [] + pid = 0 for tcb in tcbs: pid = int(tcb["pid"]) - for frame in utils.get_thread_frames(pid): - if "_assert" in utils.get_frame_func_name(frame): - collected.append(tcb) - break + if is_thread_crashed(pid): + collected.append(get_thread_info(tcb)) + + # Analysis the g_last_regs if we have running target (or nxstub) + if type(gdb.selected_inferior().connection) is gdb.RemoteTargetConnection: + running_tasks = utils.get_running_tcbs() + for n in range(utils.get_ncpus()): + gdb.execute(f"setregs g_last_regs[{n}]") + if is_thread_crashed(pid): + tcb = running_tasks[n] + collected.append( + ThreadInfo( + pid=tcb.pid if tcb else -1 - n, + name=f"g_last_regs[{n}]-" + + (utils.get_task_name(tcb) if tcb else ""), + backtrace=utils.Backtrace( + utils.get_backtrace(pid) + ), # setregs affect backtrace of current thread + crashed=True, + ) + ) + + # Restore the tcb registers. + gdb.execute(f"setregs {utils.get_tcb(pid).xcp.regs}") - return collected or utils.get_running_tcbs() + return collected or [get_thread_info(tcb) for tcb in utils.get_running_tcbs()] @utils.dont_repeat_decorator def invoke(self, arg: str, from_tty: bool) -> None: @@ -52,23 +102,33 @@ class CrashThread(gdb.Command): gdb.write("No crashed threads found.\n") return - print(f"Found crashed threads\n{'PID':<4} {'Name':<10}") - for tcb in collected: - print("{:<4} {:<10}".format(tcb["pid"], utils.get_task_name(tcb))) + print(f"Found {len(collected)} crashed threads\n{'PID':<4} {'Name':<10}") + for thread in collected: + print("{:<4} {:<10}".format(thread.pid, thread.name)) + for _, func, _, _ in thread.backtrace: + print("{:<4} {:<10}".format("", func)) def diagnose(self, *args, **kwargs): - tcbs = self.collect(utils.get_tcbs()) + threads = self.collect(utils.get_tcbs()) return { "title": "Threads that seem crashed", - "summary": f"{'No' if not tcbs else len(tcbs)} threads seem crashed", - "result": "fail" if tcbs else "pass", + "summary": f"{'No' if not threads else len(threads)} threads seem crashed", + "result": "fail" if threads else "pass", "command": "crash thread", "thread": [ { - "pid": tcb["pid"], - "name": utils.get_task_name(tcb), - "backtrace": utils.Backtrace(utils.get_backtrace(int(tcb["pid"]))), + "pid": thread.pid, + "name": thread.name, + "backtrace": [ + { + "address": addr, + "function": func, + "source": src, + "line": line, + } + for addr, func, src, line in thread.backtrace + ], } - for tcb in tcbs + for thread in threads ], } -- Gitee From 21dde47a338cad03e99d57d491c99726a2371abc Mon Sep 17 00:00:00 2001 From: xuxingliang Date: Wed, 23 Apr 2025 16:49:12 +0800 Subject: [PATCH 190/235] nxstub: fix memory insert VELAPLATFO-58517 Should recalculate the index number after list is changed due to new memory inserted. Change-Id: If41536e4c2fb382b4a719dcd2c7d58f810df2758 Signed-off-by: xuxingliang --- tools/pynuttx/nxstub/target.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tools/pynuttx/nxstub/target.py b/tools/pynuttx/nxstub/target.py index a21f59511b6..68e02816f7f 100644 --- a/tools/pynuttx/nxstub/target.py +++ b/tools/pynuttx/nxstub/target.py @@ -267,10 +267,12 @@ class Target: # Remove overlapping memory regions end = m.address + len(m) + i = memories.index(m) # Recalculate index, in case of list changed for m2 in memories[i + 1 :]: if end < m2.address: break + self.logger.debug(f"Remove overlapping memory: {m2}") memories.remove(m2) m.data += m2.data[end - m2.address :] -- Gitee From 66af800f144b8612800e421c230620322e2bf220 Mon Sep 17 00:00:00 2001 From: xuxingliang Date: Mon, 21 Apr 2025 19:27:20 +0800 Subject: [PATCH 191/235] nxgdb: add crashed thread entry information VELAPLATFO-53274 Report the crashed thread entry function address, source file and line. E.g. { "title": "Threads that seem crashed", "summary": "1 threads seem crashed", "result": "fail", "command": "crash thread", "thread": [ { "pid": "0", "name": "Idle_Task", "entry": { "address": 31485, "function": "", "source": "/vela/nuttx/sched/init/nx_start.c", "line": 643 }, "backtrace": [] } ] }, Change-Id: I14bd7ce72f89f9203d1fc00965d72f91bbedf1c0 Signed-off-by: xuxingliang --- tools/pynuttx/nxgdb/nxcrash/thread.py | 1 + tools/pynuttx/nxgdb/utils.py | 23 +++++++++++++++++++++++ 2 files changed, 24 insertions(+) diff --git a/tools/pynuttx/nxgdb/nxcrash/thread.py b/tools/pynuttx/nxgdb/nxcrash/thread.py index a2dd468eed0..3dc4132b157 100644 --- a/tools/pynuttx/nxgdb/nxcrash/thread.py +++ b/tools/pynuttx/nxgdb/nxcrash/thread.py @@ -119,6 +119,7 @@ class CrashThread(gdb.Command): { "pid": thread.pid, "name": thread.name, + "entry": utils.get_task_entry(utils.get_tcb(thread.pid)), "backtrace": [ { "address": addr, diff --git a/tools/pynuttx/nxgdb/utils.py b/tools/pynuttx/nxgdb/utils.py index 9eebe08cb1a..3b0d37b8472 100644 --- a/tools/pynuttx/nxgdb/utils.py +++ b/tools/pynuttx/nxgdb/utils.py @@ -174,6 +174,10 @@ class Symbol: and self._symtab_and_line.symtab.is_valid() ) + @property + def funcname(self) -> str: + return self.func + @property def filename(self) -> str: if not self.is_valid(): @@ -191,6 +195,14 @@ class Symbol: f"" ) + def toJSON(self): + return { + "address": self.address, + "function": self.funcname, + "source": self.filename, + "line": self.line, + } + class Backtrace: """ @@ -940,6 +952,17 @@ def get_task_name(tcb): return "" +def get_task_entry(tcb) -> Symbol: + if not tcb: + return None + + try: + entry = tcb["entry"]["main"] + return Symbol(entry) + except gdb.error: + return None + + def task_is_running(tcb): return tcb["task_state"] == get_symbol_value("TSTATE_TASK_RUNNING") -- Gitee From ccfe08771759e62d32dce3cf8bfa3c699bceb15e Mon Sep 17 00:00:00 2001 From: xuxingliang Date: Thu, 10 Apr 2025 21:18:51 +0800 Subject: [PATCH 192/235] nxgdb/stack: speed up stack usage by reading whole memory in one command VELAPLATFO-57847 When using gdbserver.py or doing online debug, read the whole stack memory to python and compare them one by one is more efficient. Change-Id: I277caea985cc0ed693525ab2501719f484baef8d Signed-off-by: xuxingliang --- tools/pynuttx/nxgdb/stack.py | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/tools/pynuttx/nxgdb/stack.py b/tools/pynuttx/nxgdb/stack.py index d25e67c2568..1c0e946f535 100644 --- a/tools/pynuttx/nxgdb/stack.py +++ b/tools/pynuttx/nxgdb/stack.py @@ -100,15 +100,13 @@ class Stack(object): return usage def check_max_usage(self): - ptr_4bytes = gdb.Value(self._stack_base).cast( - utils.lookup_type("unsigned int").pointer() - ) - spare = 0 - - for i in range(0, self._stack_size // 4): - if int(ptr_4bytes[i]) != self._pattern: - spare = i * 4 + memory = gdb.selected_inferior().read_memory(self._stack_base, self._stack_size) + size = utils.sizeof("int") + pattern = int(self._pattern).to_bytes(size, byteorder="little") + for i in range(0, self._stack_size // size): + if bytes(memory[i * size : (i + 1) * size]) != pattern: + spare = i * size break return self._stack_size - spare -- Gitee From 39af2e776c76dae137001c55dd35ee7d30fe1103 Mon Sep 17 00:00:00 2001 From: wangmingrong1 Date: Thu, 17 Apr 2025 15:23:56 +0800 Subject: [PATCH 193/235] gdb setregs: If tcb is currently running, setregs is not performed. VELAPLATFO-59181 Change-Id: I4b30da4c4da6bb1f4152eac1b34706f4f1cf12bd Signed-off-by: wangmingrong1 (cherry picked from commit 84b629e8e45f6d6bef07c2e8899a14c9dc6bcbd1) --- tools/pynuttx/nxgdb/thread.py | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/tools/pynuttx/nxgdb/thread.py b/tools/pynuttx/nxgdb/thread.py index cd3a105c386..0e9031692fc 100644 --- a/tools/pynuttx/nxgdb/thread.py +++ b/tools/pynuttx/nxgdb/thread.py @@ -311,7 +311,9 @@ class Nxthread(gdb.Command): except gdb.error and UnicodeDecodeError: gdb.write(f"Thread {i}\n") - gdb.execute(f"setregs g_pidhash[{i}]->xcp.regs") + if not utils.task_is_running(tcb): + gdb.execute(f"setregs g_pidhash[{i}]->xcp.regs") + cmd_arg = "" for cmd in arg[2:]: cmd_arg += cmd + " " @@ -343,7 +345,9 @@ class Nxthread(gdb.Command): except gdb.error and UnicodeDecodeError: gdb.write(f"Thread {i}\n") - gdb.execute(f"setregs g_pidhash[{i}]->xcp.regs") + if not utils.task_is_running(utils.get_tcb(i)): + gdb.execute(f"setregs g_pidhash[{i}]->xcp.regs") + gdb.write(gdb.execute(f"{cmd}\n", to_string=True)) g_registers.restore() -- Gitee From cdb0ce633a7b7bc4fc515ca7b0abdee3734e7222 Mon Sep 17 00:00:00 2001 From: ganjing Date: Thu, 27 Mar 2025 18:54:45 +0800 Subject: [PATCH 194/235] feat: critmon GDB Plugin Implementation VELAPLATFO-57224 usage: (gdb) critmon example: (gdb)critmon Output: PID NAME Preemption MaxCaller CritSection MaxCaller BusywaitStart Caller BusywaitMax MaxCaller BusywaitAll ThreadRunMax ThreadRunAll - CPU0 - - - - - - - - - - - 0 Idle_Task - - - - - - - - - 514907964 2929087599 1 loop_task - - - - - - - - - 826495 51111395 2 rpmsgdev_server - - - - - - - - - 9457 9457 Change-Id: Ic9b243a767303ecf3575974e284a434ae4cb5b51 Signed-off-by: ganjing --- tools/pynuttx/nxgdb/critmon.py | 161 +++++++++++++++++++++++++++++++++ 1 file changed, 161 insertions(+) create mode 100644 tools/pynuttx/nxgdb/critmon.py diff --git a/tools/pynuttx/nxgdb/critmon.py b/tools/pynuttx/nxgdb/critmon.py new file mode 100644 index 00000000000..852b682eeb8 --- /dev/null +++ b/tools/pynuttx/nxgdb/critmon.py @@ -0,0 +1,161 @@ +############################################################################ +# tools/pynuttx/nxgdb/critmon.py +# +# Licensed to the Apache Software Foundation (ASF) under one or more +# contributor license agreements. See the NOTICE file distributed with +# this work for additional information regarding copyright ownership. The +# ASF licenses this file to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance with the +# License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# +############################################################################ + +from dataclasses import dataclass +from typing import Optional + +import gdb + +from . import utils + + +@dataclass +class CriticalData: + """Data class to hold critical data information""" + + pid: Optional[int] = None + name: Optional[str] = None + premp_max: Optional[int] = None + premp_max_caller: Optional[int] = None + crit_max: Optional[int] = None + crit_max_caller: Optional[int] = None + busywait_start: Optional[int] = None + busywait_caller: Optional[int] = None + busywait_max: Optional[int] = None + busywait_max_caller: Optional[int] = None + busywait_total: Optional[int] = None + run_max: Optional[int] = None + run_time: Optional[int] = None + + def __str__(self): + """Format the information for output""" + + def fmt(field, hex: bool = False): + val = getattr(self, field) + if val is None: + return "-" + if hex and isinstance(val, int): + return hex(val) + return str(val) + + formatter = ( + "{:<3} {:<18} " + "{:<10} {:<9} " + "{:<11} {:<9} " + "{:<13} {:<6} " + "{:<11} {:<9} " + "{:<11} " + "{:<12} {}" + ) + + return formatter.format( + fmt("pid"), + fmt("name"), + fmt("premp_max"), + fmt("premp_max_caller", hex=True), + fmt("crit_max"), + fmt("crit_max_caller", hex=True), + fmt("busywait_start"), + fmt("busywait_caller", hex=True), + fmt("busywait_max"), + fmt("busywait_max_caller", hex=True), + fmt("busywait_total"), + fmt("run_max"), + fmt("run_time"), + ) + + +class Critmon(gdb.Command): + """Dump critical resource busy-wait time""" + + def __init__(self): + if not utils.get_symbol_value("CONFIG_SYSTEM_CRITMONITOR"): + print("Critmon is not enabled in the current configuration") + return + super().__init__("critmon", gdb.COMMAND_USER) + + def process_task_critical_data(self, tcb): + """Generate information for a single task's critical section""" + try: + data = CriticalData() + for name in utils.get_fieldnames("struct tcb_s"): + if hasattr(CriticalData, name): + value = getattr(tcb, name) + if name == "name": + value = value.cast(gdb.lookup_type("char").pointer()).string() + setattr(data, name, value) + return data + except Exception as e: + print(f"Error processing task critical section information: {str(e)}") + return None + + def process_global_critical_data(self): + """Generate information for global critical sections""" + try: + output = [] + for cpu, data in enumerate( + [CriticalData() for _ in range(utils.get_ncpus())] + ): + setattr(data, "name", f"CPU{cpu}") + for key in ("premp_max", "crit_max", "busywait_max", "busywait_total"): + value = utils.gdb_eval_or_none(f"g_{key}") + if not value: + continue + setattr(data, key, int(value[cpu])) + output.append(data) + return output + except Exception as e: + print(f"Error processing global critical section information: {str(e)}") + return [] + + @utils.dont_repeat_decorator + def invoke(self, args, from_tty): + # header for critical section output + print( + "PID NAME " + "Preemption MaxCaller " + "CritSection MaxCaller " + "BusywaitStart Caller " + "BusywaitMax MaxCaller " + "BusywaitAll " + "ThreadRunMax ThreadRunAll" + ) + + try: + # process global critical data + for data in self.process_global_critical_data(): + print(data) + + # process task critical data + for tcb in utils.get_tcbs(): + if not (data := self.process_task_critical_data(tcb)): + continue + print(data) + except Exception as e: + print(f"Error invoking critmon command: {str(e)}") + + def diagnose(self, *args, **kwargs): + return { + "title": "critmon report", + "summary": "critical resource busy-wait time dump", + "result": "info", + "command": "critmon", + "data": gdb.execute("critmon", to_string=True), + } -- Gitee From 897b708694ebab6709f492e25cb0dcb62f05a642 Mon Sep 17 00:00:00 2001 From: yinshengkai Date: Mon, 14 Apr 2025 23:26:40 +0800 Subject: [PATCH 195/235] nxtrace: add rtt generic implementationa VELAPLATFO-58367 Change-Id: Id469ec3062f978723f7bfa87697fe52dc6d8affe Signed-off-by: yinshengkai --- tools/pynuttx/nxtrace/general_rtt.py | 346 +++++++++++++++++++++++++++ tools/pynuttx/requirements.txt | 2 + 2 files changed, 348 insertions(+) create mode 100644 tools/pynuttx/nxtrace/general_rtt.py diff --git a/tools/pynuttx/nxtrace/general_rtt.py b/tools/pynuttx/nxtrace/general_rtt.py new file mode 100644 index 00000000000..73b4578c963 --- /dev/null +++ b/tools/pynuttx/nxtrace/general_rtt.py @@ -0,0 +1,346 @@ +############################################################################ +# tools/pynuttx/nxtrace/general_rtt.py +# +# SPDX-License-Identifier: Apache-2.0 +# +# Licensed to the Apache Software Foundation (ASF) under one or more +# contributor license agreements. See the NOTICE file distributed with +# this work for additional information regarding copyright ownership. The +# ASF licenses this file to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance with the +# License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# +############################################################################ + +import logging +from abc import ABC, abstractmethod +from ctypes import Structure, c_char, c_int32, c_uint32, c_uint64, c_void_p, sizeof +from multiprocessing import shared_memory +from typing import Union + +try: + import lauterbach.trace32.rcl as trace32 + from pylink.jlink import JLink +except ImportError: + print("Please execute the following command to install dependencies:") + print("pip install lauterbach-trace32-rcl pylink-square") + exit(1) + +log = logging.getLogger(__name__) + + +class SEGGER_RTT_CB(Structure): + _fields_ = [ + ("acID", c_char * 16), + ("MaxNumUpBuffers", c_int32), + ("MaxNumDownBuffers", c_int32), + ] + + +class SEGGER_RTT_BUFFER_UP(Structure): + _fields_ = [ + ("sName", c_void_p), + ("pBuffer", c_void_p), + ("SizeOfBuffer", c_uint32), + ("WrOff", c_uint32), + ("RdOff", c_uint32), + ("Flags", c_uint32), + ] + + +class SEGGER_RTT_BUFFER_DOWN(Structure): + _fields_ = [ + ("sName", c_void_p), + ("pBuffer", c_void_p), + ("SizeOfBuffer", c_uint32), + ("WrOff", c_uint32), + ("RdOff", c_uint32), + ("Flags", c_uint32), + ] + + +def struct_factory(cls, bitwidth=32): + class MeteStructure(type): + def __new__(cls, name, bases, attrs, bitwidth=32): + if "_fields_" in attrs: + realfields = list() + for field in attrs["_fields_"]: + if field[1] == c_void_p: + field = (field[0], c_uint32 if bitwidth == 32 else c_uint64) + realfields.append(field) + else: + raise ValueError("No _fields_ in class") + + class DynamicStructure(Structure): + _fields_ = realfields + fields = {field[0]: field[1] for field in realfields} + + return DynamicStructure + + class DynamicStructure(metaclass=MeteStructure, bitwidth=bitwidth): + _fields_ = cls._fields_ + + return DynamicStructure + + +class MemoryController(ABC): + @abstractmethod + def read(self, addr: int, size: int) -> bytes: + """Read data from memory""" + pass + + @abstractmethod + def write(self, addr: int, data: Union[bytes, int]) -> int: + """Write data to memory""" + pass + + +# This class is used to read and write to a structure in memory +class Value: + def __init__( + self, + controller: MemoryController, + struct: type(Structure), + addr: int = None, + ): + if addr is None: + raise ValueError("Must specify addr") + + self.struct = struct + self.controller = controller + self.address = addr + + def read(self): + data = self.controller.read(self.address, sizeof(self.struct)) + if len(data) == 0: + return b"" + parsed = self.struct.from_buffer_copy(data) + for field, _ in self.struct._fields_: + self._cache[field] = getattr(parsed, field) + + def __getattr__(self, key): + if key in self.struct.fields: + offset = getattr(self.struct, key).offset + size = getattr(self.struct, key).size + data = self.controller.read(self.address + offset, size) + parsed = self.struct.fields[key].from_buffer_copy(data).value + log.debug("parsed %s: %s", key, parsed) + return parsed + else: + return super().__getattribute__(key) + + def __setattr__(self, key, value): + if key == "struct": + super().__setattr__(key, value) + elif key in self.struct.fields: + offset = getattr(self.struct, key).offset + self.controller.write(self.address + offset, value) + else: + super().__setattr__(key, value) + + +class RTTUpChannel: + def __init__(self, up: Value): + self.up = up + + def read(self): + address = self.up.pBuffer + wroff = self.up.WrOff + rdoff = self.up.RdOff + + if wroff == rdoff: + return b"" + elif wroff > rdoff: + data = self.up.controller.read(address + rdoff, wroff - rdoff) + self.up.RdOff = wroff + return data + else: + size = self.up.SizeOfBuffer - rdoff + data = self.up.controller.read(address + rdoff, size) + data += self.up.controller.read(address, wroff) + self.up.RdOff = wroff + return data + + +class RTTDownChannel: + def __init__(self, down: Value): + self.down = down + + def write(self, data: bytes, blocking: bool = False): + if blocking: + while data: + sent = self.write(data, blocking=False) + data = data[sent:] + return + + address = self.down.pBuffer + wroff = self.down.WrOff + rdoff = self.down.RdOff + size = self.down.SizeOfBuffer + + if wroff >= size or rdoff >= size: + raise ValueError("Invalid down buffer") + + written = 0 + if wroff >= rdoff: + remaining = size - wroff + if rdoff == 0: + remaining -= 1 + + data_to_write = data[:remaining] + self.down.controller.write(address + wroff, data_to_write) + written = len(data_to_write) + data = data[written:] + wroff = (wroff + written) % size + + remaining = rdoff - wroff - 1 + if remaining < 0: + remaining = 0 + + num = min(remaining, len(data)) + self.down.controller.write(address + wroff, data[:num]) + written += num + wroff += num + + self.down.WrOff = wroff + return written + + +class SEGGER_RTT: + def __init__(self, memory: MemoryController, addr: int = None, bitwidth: int = 32): + self.SEGGER_RTT_CB = struct_factory(SEGGER_RTT_CB, bitwidth) + self.SEGGER_RTT_BUFFER_UP = struct_factory(SEGGER_RTT_BUFFER_UP, bitwidth) + self.SEGGER_RTT_BUFFER_DOWN = struct_factory(SEGGER_RTT_BUFFER_DOWN, bitwidth) + + self.rtt_cb = Value(memory, self.SEGGER_RTT_CB, addr=addr) + self.upbuffer = [bytes() for _ in range(self.rtt_cb.MaxNumUpBuffers)] + self.downbuffer = [bytes() for _ in range(self.rtt_cb.MaxNumDownBuffers)] + + self.aUp = [ + RTTUpChannel( + Value( + memory, + self.SEGGER_RTT_BUFFER_UP, + self.rtt_cb.address + + sizeof(self.SEGGER_RTT_BUFFER_UP) * i + + sizeof(self.SEGGER_RTT_CB), + ) + ) + for i in range(self.rtt_cb.MaxNumUpBuffers) + ] + + self.aDown = [ + RTTDownChannel( + Value( + memory, + self.SEGGER_RTT_BUFFER_DOWN, + self.rtt_cb.address + + sizeof(self.SEGGER_RTT_BUFFER_DOWN) * i + + sizeof(self.SEGGER_RTT_BUFFER_UP) * self.rtt_cb.MaxNumUpBuffers + + sizeof(self.SEGGER_RTT_CB), + ) + ) + for i in range(self.rtt_cb.MaxNumDownBuffers) + ] + + def read(self, channel: int, size: int = -1) -> bytes: + if channel in range(self.rtt_cb.MaxNumUpBuffers): + self.upbuffer[channel] += self.aUp[channel].read() + if size == -1: + data = self.upbuffer[channel] + self.upbuffer[channel] = bytes() + else: + data = self.upbuffer[channel][:size] + self.upbuffer[channel] = self.upbuffer[channel][size:] + return data + else: + raise ValueError("Invalid channel") + + def write(self, channel: int, data: bytes, blocking: bool = False): + if channel in range(self.rtt_cb.MaxNumDownBuffers): + self.aDown[channel].write(data, blocking) + else: + raise ValueError("Invalid channel") + + +class Trace32MemoryController(MemoryController): + def __init__(self, debugger: trace32.Debugger): + self.debugger = debugger + self._addr = dict() + + def read(self, addr: int, size: int) -> bytes: + if addr not in self._addr: + self._addr[addr] = self.debugger.address(access="E", value=addr) + + ret = self.debugger.memory.read_uint8_array( + self._addr[addr], length=size + ).tobytes() + log.debug("trace32 read %#x len:%d %s", addr, size, ret) + return ret + + def write(self, addr: int, data: Union[bytes, int]) -> int: + if addr not in self._addr: + self._addr[addr] = self.debugger.address(access="D", value=addr) + + if isinstance(data, int): + value = data.to_bytes(length=4, byteorder="little") + else: + value = data + + ret = self.debugger.memory.write_uint8_array(self._addr[addr], value) + log.debug("trace32 write %#x len:%d %s", addr, len(value), ret) + return ret + + +class JlinkMemoryController(MemoryController): + def __init__(self, debugger: JLink): + self.debugger = debugger + + def read(self, addr: int, size: int) -> bytes: + ret = bytes(self.debugger.memory_read8(addr=addr, num_bytes=size)) + log.debug("jlink read %#x len:%d %s", addr, size, ret) + return ret + + def write(self, addr: int, data: Union[bytes, int]) -> int: + if isinstance(data, int): + data = data.to_bytes(length=4, byteorder="little") + + ret = self.debugger.memory_write8(addr=addr, data=data) + log.debug("jlink write %#x len:%d %s", addr, len(data), ret) + return ret + + +class ShmMemoryController(MemoryController): + def __init__(self, name: str, rttaddr: int): + self.shm = shared_memory.SharedMemory(name=name) + self.rttaddr = rttaddr + self.rttoffset = self.shm.buf.tobytes().find(b"SEGGER RTT") + + def read(self, addr: int, size: int) -> bytes: + offset = addr - self.rttaddr + self.rttoffset + if offset < 0 or offset + size > self.shm.size: + raise ValueError("Invalid address") + + ret = self.shm.buf[offset : offset + size].tobytes() + log.debug(f"shm read 0x{addr:x}(offset:{offset}) size:{size} {ret}") + return ret + + def write(self, addr: int, data: Union[bytes, int]) -> int: + offset = addr - self.rttaddr + self.rttoffset + if isinstance(data, int): + data = data.to_bytes(length=4, byteorder="little") + + if offset < 0 or offset + len(data) > self.shm.size: + raise ValueError("Invalid address") + + self.shm.buf[offset : offset + len(data)] = data + log.debug(f"shm write 0x{addr:x}(offset:{offset}) size:{len(data)} {data}") + return len(data) diff --git a/tools/pynuttx/requirements.txt b/tools/pynuttx/requirements.txt index f3e81ff2134..d4d2c0e028e 100644 --- a/tools/pynuttx/requirements.txt +++ b/tools/pynuttx/requirements.txt @@ -2,6 +2,7 @@ angr capstone construct debugpy +lauterbach-trace32-rcl lief matplotlib numpy @@ -9,3 +10,4 @@ pandas pillow plotly pyelftools +pylink-square -- Gitee From dc29604a3bcb6779f2d3247b365caaa658a738f7 Mon Sep 17 00:00:00 2001 From: wangmingrong1 Date: Thu, 24 Apr 2025 17:48:23 +0800 Subject: [PATCH 196/235] gdb plugin: Catch an unknown error and print the call stack VELAPLATFO-59270 Change-Id: I3bd22c896ec7d18b440bcf20b25994342314a204 Signed-off-by: wangmingrong1 --- tools/pynuttx/nxgdb/utils.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tools/pynuttx/nxgdb/utils.py b/tools/pynuttx/nxgdb/utils.py index 3b0d37b8472..63851ba29b5 100644 --- a/tools/pynuttx/nxgdb/utils.py +++ b/tools/pynuttx/nxgdb/utils.py @@ -30,6 +30,7 @@ import math import re import shlex import sys +import traceback from enum import Enum from pathlib import Path from typing import List, Optional, Union @@ -352,7 +353,7 @@ def dont_repeat_decorator(func): self.dont_repeat() func(self, args, from_tty) except Exception as e: - print(f"Error: {e}") + print(f"Error: {e}\n{traceback.format_exc()}") return wrapper -- Gitee From f98d5c6a9d1262c5d52da6db89adfff953a015bd Mon Sep 17 00:00:00 2001 From: wangmingrong1 Date: Thu, 24 Apr 2025 21:02:17 +0800 Subject: [PATCH 197/235] gdb plugin: Temporarily skip the mock test VELAPLATFO-59270 The mock test will cause the NuttX system to fail, waiting for repair Change-Id: I5a182402a1c66e6112c389aac10895f442510583 Signed-off-by: wangmingrong1 --- tools/pynuttx/tests/runner.py | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/tools/pynuttx/tests/runner.py b/tools/pynuttx/tests/runner.py index 7403e247697..bce123877a1 100755 --- a/tools/pynuttx/tests/runner.py +++ b/tools/pynuttx/tests/runner.py @@ -24,9 +24,6 @@ import unittest if __name__ == "__main__": test_dir = os.path.dirname(os.path.abspath(__file__)) - testsuit_mock = unittest.defaultTestLoader.discover( - test_dir, pattern="test_mock*.py" - ) testsuit_runtime = unittest.defaultTestLoader.discover( test_dir, pattern="test_runtime*.py" ) @@ -36,9 +33,13 @@ if __name__ == "__main__": # NOTE: Run the runtime testsuit first, as we are going to mock # lots of methods as well as classes later! result_runtime = test_runner.run(testsuit_runtime) - result_mock = test_runner.run(testsuit_mock) - if not result_runtime.wasSuccessful() or not result_mock.wasSuccessful(): + """ testsuit_mock = unittest.defaultTestLoader.discover( + test_dir, pattern="test_mock*.py" + ) + result_mock = test_runner.run(testsuit_mock) """ + + if not result_runtime.wasSuccessful(): print("GDB Plugin Test Failed") else: print("GDB Plugin Test Successfully") -- Gitee From d50bf33fe1403b160a1c79ebc6f5a8e8b2c238ea Mon Sep 17 00:00:00 2001 From: xuxingliang Date: Thu, 24 Apr 2025 12:14:47 +0800 Subject: [PATCH 198/235] nxgdb/memleak: fix wrong report of heap guard as leak VELAPLATFO-59245 The heap struct itself locates in heap head, but not included in any nodes. Manually exclude them from checking. (gdb) mm leak Loading globals from elf... 0.01s Gather memory nodes... 0.02s Leak analyzing... 0.02s Pool CNT PID NodeSize Overhead Seqno Address Backtrace H 2 0 20 20 0 0x1005b98 H 1 0 20 20 13 0xa0000000 /home/neo/pool/lessions/vela/nuttx/libs/libc/misc/lib_backtrace.c:325 /home/neo/pool/lessions/vela/nuttx/mm/mm_heap/mm_initialize.c:186 /home/neo/pool/lessions/vela/nuttx/mm/umm_heap/umm_addregion.c:56 /home/neo/pool/lessions/vela/nuttx/arch/arm/src/mps/mps_allocateheap.c:283 /home/neo/pool/lessions/vela/nuttx/arch/arm/src/common/arm_initialize.c:105 /home/neo/pool/lessions/vela/nuttx/sched/init/nx_start.c:823 <__start+78> /home/neo/pool/lessions/vela/nuttx/arch/arm/src/mps/mps_start.c:191 H 1 0 20 20 14 0xa3ffffec /home/neo/pool/lessions/vela/nuttx/libs/libc/misc/lib_backtrace.c:325 /home/neo/pool/lessions/vela/nuttx/mm/mm_heap/mm_initialize.c:197 /home/neo/pool/lessions/vela/nuttx/mm/umm_heap/umm_addregion.c:56 /home/neo/pool/lessions/vela/nuttx/arch/arm/src/mps/mps_allocateheap.c:283 /home/neo/pool/lessions/vela/nuttx/arch/arm/src/common/arm_initialize.c:105 /home/neo/pool/lessions/vela/nuttx/sched/init/nx_start.c:823 <__start+78> /home/neo/pool/lessions/vela/nuttx/arch/arm/src/mps/mps_start.c:191 Leaked 4 blks, 80 bytes (gdb) Change-Id: I05112261554ef8e164f2af985d5b84b3c8775acc Signed-off-by: xuxingliang --- tools/pynuttx/nxgdb/memleak.py | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/tools/pynuttx/nxgdb/memleak.py b/tools/pynuttx/nxgdb/memleak.py index 61350dfa977..e4e2a47dd2b 100644 --- a/tools/pynuttx/nxgdb/memleak.py +++ b/tools/pynuttx/nxgdb/memleak.py @@ -114,9 +114,20 @@ class MMLeak(gdb.Command): sorted_addr = set() t = time.time() print("Gather memory nodes...", flush=True, end="") + + heap_guards = [ + item + for heap in heaps + for start, end in heap.regions + for item in (start, end) + ] + for node in memdump.dump_nodes( heaps, {"no_pid": mm.PID_MM_MEMPOOL, "used": True} ): + if node in heap_guards: + continue + nodes_dict[node.address] = node sorted_addr.add(node.address) -- Gitee From 48579e1b5b15f5ffe2e556c9adbc10c5befe998d Mon Sep 17 00:00:00 2001 From: xuxingliang Date: Fri, 25 Apr 2025 11:25:43 +0800 Subject: [PATCH 199/235] nxstub: fix raw memory parsing VELAPLATFO-59274 Need to extract the file name before open it when address is specified in parameters. Need to make the rawfile a list. Change-Id: I27bd99ab8e0575fb9eefe61ea872c8be1fe9d7ec Signed-off-by: xuxingliang --- tools/pynuttx/nxstub/__init__.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tools/pynuttx/nxstub/__init__.py b/tools/pynuttx/nxstub/__init__.py index 73a08b22b9d..a3d9b6c07ca 100644 --- a/tools/pynuttx/nxstub/__init__.py +++ b/tools/pynuttx/nxstub/__init__.py @@ -155,7 +155,7 @@ def auto_parse_dump(args): args.log = dump elif dump.endswith(".bin"): print(f"Input is raw memory dump: {dump}") - args.rawfile = dump + args.rawfile = [dump] elif is_core_file(dump): print(f"Input is core dump: {dump}") args.core = dump @@ -199,7 +199,7 @@ def gdbstub_start(args): print(f"Add memory dump: {memories[-1]}") else: address = get_address(name) - with open(name, "rb") as f: + with open(name.split(":")[0], "rb") as f: memories.append(RawMemory(address, f.read())) print(f"Add memory dump: {memories[-1]}") -- Gitee From 026d1326dc54f012b75901869413739d89c7db02 Mon Sep 17 00:00:00 2001 From: xuxingliang Date: Fri, 25 Apr 2025 11:44:17 +0800 Subject: [PATCH 200/235] nxgdb/crash: fix backtrace error VELAPLATFO-59274 Now the backtrace returns addr, func, src, and line. Change-Id: Iad998f6fa55143c53a80eab63909ed499e9c0d1d Signed-off-by: xuxingliang --- tools/pynuttx/nxgdb/nxcrash/thread.py | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/tools/pynuttx/nxgdb/nxcrash/thread.py b/tools/pynuttx/nxgdb/nxcrash/thread.py index 3dc4132b157..72198d8705f 100644 --- a/tools/pynuttx/nxgdb/nxcrash/thread.py +++ b/tools/pynuttx/nxgdb/nxcrash/thread.py @@ -120,15 +120,7 @@ class CrashThread(gdb.Command): "pid": thread.pid, "name": thread.name, "entry": utils.get_task_entry(utils.get_tcb(thread.pid)), - "backtrace": [ - { - "address": addr, - "function": func, - "source": src, - "line": line, - } - for addr, func, src, line in thread.backtrace - ], + "backtrace": thread.backtrace, } for thread in threads ], -- Gitee From 5ae8b8a02bd314001807f0cad02a068e274d0a2c Mon Sep 17 00:00:00 2001 From: xuxingliang Date: Tue, 8 Apr 2025 11:57:30 +0800 Subject: [PATCH 201/235] nxgdb/target: automatically parse current arch for nxstub VELAPLATFO-56229 GDB can tell current arch from elf file, thus no need to manually select arch for nxstub. Change-Id: I463eb58b2e19c9780f370fe46515db2d5fdf0610 Signed-off-by: xuxingliang --- tools/pynuttx/nxgdb/target.py | 10 +++++++++- tools/pynuttx/nxgdb/thread.py | 17 ++++------------- tools/pynuttx/nxreg/register.py | 16 ++++++++++++++++ 3 files changed, 29 insertions(+), 14 deletions(-) diff --git a/tools/pynuttx/nxgdb/target.py b/tools/pynuttx/nxgdb/target.py index 0f4df712a21..920748a7efd 100644 --- a/tools/pynuttx/nxgdb/target.py +++ b/tools/pynuttx/nxgdb/target.py @@ -24,6 +24,7 @@ import multiprocessing import gdb import nxstub +from nxreg.register import get_arch_name from . import utils @@ -43,8 +44,12 @@ class Target(gdb.Command): if "-e" not in args and "--elf" not in args: args += f" -e {gdb.objfiles()[0].filename}" + arch = get_arch_name() # Convert to nxstub arch name + if "-a" not in args and "--arch" not in args: - args += f" -a {gdb.selected_inferior().architecture().name().lower()}" + args += f" -a {arch}" + else: + print(f"Hint: no need to specify architecture, current arch: {arch}") args = gdb.string_to_argv(args) try: @@ -52,6 +57,9 @@ class Target(gdb.Command): except SystemExit: return + if parsed.arch != arch: + print(f"Warning: current arch {arch} does not match nxstub {parsed.arch}") + # If currently has connection to target, disconnect it inferior = gdb.selected_inferior() if inferior and inferior.connection and inferior.connection.is_valid(): diff --git a/tools/pynuttx/nxgdb/thread.py b/tools/pynuttx/nxgdb/thread.py index 0e9031692fc..b588d04021a 100644 --- a/tools/pynuttx/nxgdb/thread.py +++ b/tools/pynuttx/nxgdb/thread.py @@ -26,7 +26,7 @@ from typing import Union import gdb from nxelf.elf import LiefELF -from nxreg.register import Registers, g_reg_table +from nxreg.register import Registers, get_arch_name from . import utils from .stack import Stack @@ -48,21 +48,12 @@ class NxRegisters: def read_memory(addr, size): return bytes(gdb.selected_inferior().read_memory(addr, size)) - arch = gdb.selected_inferior().architecture() - mapped_arch_name = self.map_gdbarch_name(arch.name()) - if mapped_arch_name not in g_reg_table: - raise ValueError( - f"Architecture {mapped_arch_name} is not found in g_reg_table.\n" - ) + mapped_arch_name = get_arch_name() + if not mapped_arch_name: + raise ValueError("Architecture is not found in g_reg_table.\n") self.registers = Registers(elf, arch=mapped_arch_name, readmem=read_memory) - def map_gdbarch_name(self, arch: str): - for arch_key, arch_info in g_reg_table.items(): - if arch in arch_info["architecture"]: - return arch_key - return None - def load(self, regs: Union[int, gdb.Value] = None): """Load registers from context register address""" self.registers.load(regs) diff --git a/tools/pynuttx/nxreg/register.py b/tools/pynuttx/nxreg/register.py index ec746c2d4ad..1c0daf2951c 100644 --- a/tools/pynuttx/nxreg/register.py +++ b/tools/pynuttx/nxreg/register.py @@ -571,3 +571,19 @@ def Registers(elf, arch=None, readmem=None) -> GeneralRegisters: return TricoreRegisters(elf, arch, readmem) else: return GeneralRegisters(elf, arch, readmem) + + +def get_arch_name(): + """ + GDB uses arch name like aarch64, while we use arm64 to identify the register set. + This function maps the GDB arch name to our arch name. + """ + import gdb + + gdb_arch = gdb.selected_inferior().architecture() + gdb_arch = gdb_arch.name().lower() + + for arch_key, arch_info in g_reg_table.items(): + if gdb_arch in arch_info["architecture"]: + return arch_key + return None -- Gitee From 6f9a0612e336bdaa6d0593cb9dee71e5e35272b3 Mon Sep 17 00:00:00 2001 From: ganjing Date: Wed, 12 Mar 2025 20:13:10 +0800 Subject: [PATCH 202/235] feat: noteram GDB Plugin Implementation VELAPLATFO-55949 Change-Id: Iefcea43380d704fde7e9c408b49e4183d7bf8e96 Signed-off-by: ganjing --- tools/pynuttx/nxgdb/noteram.py | 129 +++++++++++++++++++++++++++++++++ 1 file changed, 129 insertions(+) create mode 100644 tools/pynuttx/nxgdb/noteram.py diff --git a/tools/pynuttx/nxgdb/noteram.py b/tools/pynuttx/nxgdb/noteram.py new file mode 100644 index 00000000000..82ede55f221 --- /dev/null +++ b/tools/pynuttx/nxgdb/noteram.py @@ -0,0 +1,129 @@ +############################################################################ +# tools/pynuttx/nxgdb/noteram.py +# +# Licensed to the Apache Software Foundation (ASF) under one or more +# contributor license agreements. See the NOTICE file distributed with +# this work for additional information regarding copyright ownership. The +# ASF licenses this file to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance with the +# License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# +############################################################################ + +import gdb +from nxelf.elf import ELFParser +from nxtrace.trace import NoteFactory + +from . import utils + + +class NoteRam: + def __init__(self, driver_name: str): + """Initialize NoteRam object with driver structure""" + self.driver = None + self.buffer = None + self.bufsize = 0 + self.head = 0 + self.read = 0 + + self.driver = utils.gdb_eval_or_none(driver_name) + if not self.driver: + return + self.head = int(self.driver["header"]["head"]) + self.read = int(self.driver["header"]["read"]) + self.bufsize = int(self.driver["bufsize"]) + self.buffer = ( + gdb.selected_inferior() + .read_memory(self.driver["buffer"].cast("uintptr_t"), self.bufsize) + .tobytes() + ) + + def events(self): + """Generate events from circular buffer""" + if not self.buffer or not self.bufsize: + return + + uintptr_size = utils.sizeof("uintptr_t") + buffer, bufsize, head, read = ( + self.buffer, + self.bufsize, + self.head, + self.read, + ) + while (unread := (head - read) % bufsize) > 0: + event_len = int(buffer[read]) + if event_len <= 0 or event_len > unread: + raise BufferError( + f"Invalid event length: {event_len}, available space {unread}" + ) + end = read + event_len + event = bytes( + buffer[read:end] + if end <= bufsize + else buffer[read:bufsize] + buffer[: end % bufsize] + ) + yield event + read = ( + read + ((event_len + uintptr_size - 1) & ~(uintptr_size - 1)) + ) % bufsize + + +class NoteRamCommand(gdb.Command): + """GDB command to parse and dump noteram data into a Perfetto trace file""" + + def __init__(self): + if not utils.get_field_nitems("struct noteram_driver_s", "buffer"): + return + super().__init__("noteram", gdb.COMMAND_USER) + self.initialized = False + + def init_note_factory(self): + """Initialize NoteFactory once and only once""" + if self.initialized: + return True + if path := gdb.objfiles()[0].filename: + NoteFactory.init_instance(ELFParser(path), "trace.perfetto") + self.initialized = True + return True + return False + + def collect_notes(self): + """Collect and parse notes from noteram events""" + notes = [] + if not self.init_note_factory(): + print("NoteFactory initialization failed") + return notes + + noteram = NoteRam("g_noteram_driver") + if not noteram.buffer: + print("No valid noteram buffer") + return notes + + for idx, event in enumerate(noteram.events()): + try: + if note := NoteFactory.parse(event): + notes.append(note) + except Exception as e: + print(f"Error parsing event {idx} ({event}): {e}") + return notes + + @utils.dont_repeat_decorator + def invoke(self, args, from_tty): + NoteFactory.dump(self.collect_notes()) + + def diagnose(self, *args, **kwargs): + return { + "title": "Noteram Report", + "summary": "noteram dump", + "command": "noteram", + "result": "info", + "message": self.collect_notes(), + } -- Gitee From f7c5b8f4f124b4a458bf8260698d603260b81707 Mon Sep 17 00:00:00 2001 From: ganjing Date: Fri, 11 Apr 2025 20:48:50 +0800 Subject: [PATCH 203/235] feat: exposes an interface to access system information properties VELAPLATFO-58239 Change-Id: I5455d0a1b0664f2e613a5bb519e4d3ae47b6b87e Signed-off-by: ganjing --- tools/pynuttx/nxgdb/uname.py | 37 ++++++++++++++++++++++++------------ 1 file changed, 25 insertions(+), 12 deletions(-) diff --git a/tools/pynuttx/nxgdb/uname.py b/tools/pynuttx/nxgdb/uname.py index a9c40ab6839..cbe584a9402 100644 --- a/tools/pynuttx/nxgdb/uname.py +++ b/tools/pynuttx/nxgdb/uname.py @@ -19,12 +19,37 @@ ############################################################################ import argparse +import subprocess +from os import path import gdb from . import utils +def get_commit_id(): + here = path.dirname(path.abspath(__file__)) + try: + result = subprocess.run( + ["git", "-C", here, "rev-parse", "--short", "HEAD"], + check=True, + stdout=subprocess.PIPE, + stderr=subprocess.DEVNULL, + text=True, + ) + return result.stdout.strip() + except (subprocess.CalledProcessError, FileNotFoundError): + return "unknown" + + +kernel_name = "NuttX" +node_name = str(utils.get_symbol_value("CONFIG_LIBC_HOSTNAME")).replace('"', "") +kernel_release = str(utils.get_symbol_value("CONFIG_VERSION_STRING")).replace('"', "") +kernel_version = str(utils.parse_and_eval("g_version")).replace('"', "") +machine = str(utils.get_symbol_value("CONFIG_ARCH")).replace('"', "") +tool_version = get_commit_id() + + class UnameCommand(gdb.Command): """Output specific system information""" @@ -81,22 +106,10 @@ class UnameCommand(gdb.Command): @utils.dont_repeat_decorator def invoke(self, args, from_tty): - args = self.parse_arguments(gdb.string_to_argv(args)) if not args: return - kernel_name = "NuttX" - node_name = str(utils.get_symbol_value("CONFIG_LIBC_HOSTNAME") or "").replace( - '"', "" - ) - kernel_release = str( - utils.get_symbol_value("CONFIG_VERSION_STRING") or "" - ).replace('"', "") - kernel_version = str(utils.parse_and_eval("g_version") or "").replace('"', "") - machine = str(utils.get_symbol_value("CONFIG_ARCH") or "").replace('"', "") - tool_version = "1.0.0" - if args.all: print( kernel_name, -- Gitee From 528649838961a6abbf2417332bf3725d7a044622 Mon Sep 17 00:00:00 2001 From: ganjing Date: Fri, 11 Apr 2025 11:37:27 +0800 Subject: [PATCH 204/235] feat: Verify the ELF file version against the GDB tool version VELAPLATFO-58132 Change-Id: I5cd65e2193107e1b71a015a29662cdf485195cdb Signed-off-by: ganjing --- tools/pynuttx/nxgdb/utils.py | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/tools/pynuttx/nxgdb/utils.py b/tools/pynuttx/nxgdb/utils.py index 63851ba29b5..84ae86e2672 100644 --- a/tools/pynuttx/nxgdb/utils.py +++ b/tools/pynuttx/nxgdb/utils.py @@ -1011,9 +1011,30 @@ def check_version(): gdb.write(f"Build version: {mem_version}\n") switch_inferior(1) # Switch back + # Verify the ELF file version against the GDB tool version + check_compatibility() suppress_cli_notifications(state) +def check_compatibility(): + """Check the elf and the GDB tool version""" + from . import uname + + kernel_version = uname.kernel_version + version_parts = kernel_version.split(" ") + if len(version_parts) < 1: + gdb.write(f"Invalid kernel_version format: {kernel_version}") + return + elf_version = version_parts[0] + tool_verson = uname.tool_version + + if not elf_version.startswith(tool_verson): + gdb.write( + f"\x1b[31;1mWarning: ELF version {elf_version} " + f"does not match GDB tool version {tool_verson}\x1b[m\n" + ) + + def get_task_tls(tid, key): """get task tls from tid and key""" tcb = get_tcb(tid) -- Gitee From b074e04efee419f32d840f622176b73746d73bb3 Mon Sep 17 00:00:00 2001 From: ganjing Date: Sun, 27 Apr 2025 11:51:11 +0800 Subject: [PATCH 205/235] fix: do not quit GDB if the noteram module fails to load VELAPLATFO-59378 Change-Id: Ie354f528ba737e75703f04f2d0094de61793986c Signed-off-by: ganjing --- tools/pynuttx/nxgdb/noteram.py | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/tools/pynuttx/nxgdb/noteram.py b/tools/pynuttx/nxgdb/noteram.py index 82ede55f221..85778c2d9b9 100644 --- a/tools/pynuttx/nxgdb/noteram.py +++ b/tools/pynuttx/nxgdb/noteram.py @@ -19,8 +19,12 @@ ############################################################################ import gdb -from nxelf.elf import ELFParser -from nxtrace.trace import NoteFactory + +try: + from nxelf.elf import ELFParser + from nxtrace.trace import NoteFactory +except SystemExit: + pass from . import utils -- Gitee From a9348ac312c9379e9f964be43053e0e3dcc078e1 Mon Sep 17 00:00:00 2001 From: xuxingliang Date: Tue, 22 Apr 2025 19:34:39 +0800 Subject: [PATCH 206/235] nxstub: load registers from g_last_regs for running tasks VELAPLATFO-53274 Revert nxstub: always use tcb.xcp.regs to fetch registers Most of the developers don't know how to deal with setregs command. Revert it back so most of the cases it will just work. Added hint when registers are loaded from g_last_regs. Check obvious invalid g_last_regs before using it. nxcrash/thread.py has been updated to ignore g_last_regs. Change-Id: I532a4ea3dbf10a6a2d391d25884afe7733c15639 Signed-off-by: xuxingliang --- tools/pynuttx/nxgdb/nxcrash/thread.py | 22 ------------------ tools/pynuttx/nxstub/target.py | 33 +++++++++++++++++++++++++-- 2 files changed, 31 insertions(+), 24 deletions(-) diff --git a/tools/pynuttx/nxgdb/nxcrash/thread.py b/tools/pynuttx/nxgdb/nxcrash/thread.py index 72198d8705f..e2cf3bd89e0 100644 --- a/tools/pynuttx/nxgdb/nxcrash/thread.py +++ b/tools/pynuttx/nxgdb/nxcrash/thread.py @@ -70,28 +70,6 @@ class CrashThread(gdb.Command): if is_thread_crashed(pid): collected.append(get_thread_info(tcb)) - # Analysis the g_last_regs if we have running target (or nxstub) - if type(gdb.selected_inferior().connection) is gdb.RemoteTargetConnection: - running_tasks = utils.get_running_tcbs() - for n in range(utils.get_ncpus()): - gdb.execute(f"setregs g_last_regs[{n}]") - if is_thread_crashed(pid): - tcb = running_tasks[n] - collected.append( - ThreadInfo( - pid=tcb.pid if tcb else -1 - n, - name=f"g_last_regs[{n}]-" - + (utils.get_task_name(tcb) if tcb else ""), - backtrace=utils.Backtrace( - utils.get_backtrace(pid) - ), # setregs affect backtrace of current thread - crashed=True, - ) - ) - - # Restore the tcb registers. - gdb.execute(f"setregs {utils.get_tcb(pid).xcp.regs}") - return collected or [get_thread_info(tcb) for tcb in utils.get_running_tcbs()] @utils.dont_repeat_decorator diff --git a/tools/pynuttx/nxstub/target.py b/tools/pynuttx/nxstub/target.py index 68e02816f7f..e1c45264b6c 100644 --- a/tools/pynuttx/nxstub/target.py +++ b/tools/pynuttx/nxstub/target.py @@ -28,6 +28,10 @@ from nxreg.register import Registers from . import utils +# Manually limit the maximum number of threads, in case the memory is +# corrupted to non-sense values. +MAX_THREADS = 512 + class RawMemory: def __init__(self, address: int, data: bytearray): @@ -137,7 +141,12 @@ class Target: self.logger.error(f"No threads info found: {npidhash}") return self.threads + if npidhash > MAX_THREADS: + self.logger.warning(f"g_npidhash looks wrong: {npidhash}") + npidhash = MAX_THREADS + ncpus = utils.get_ncpus(self.elf) + regsize = utils.get_regsize(self.elf) data, sym = self._read_symbol("g_running_tasks") # an array of pointers running_tasks = utils.parse_array(data, pointer, ncpus) @@ -162,8 +171,28 @@ class Target: state = utils.uint8_t(data[tcbinfo.state_off : tcbinfo.state_off + 1]) state = states[state] if state < len(states) else "Unknown" - xcpregs = data[tcbinfo.regs_off : tcbinfo.regs_off + pointer.sizeof()] - xcpregs = pointer.parse(xcpregs) + xcpregs = None + if address in running_tasks: + # Running task registers is not in memory, best chance is the registers + # stored in g_last_regs when assert happened. + last_regs = self.elf.get_symbol("g_last_regs").value + cpu = running_tasks.index(address) + xcpregs = cpu * regsize + last_regs + # Check if the g_last_regs is obviously invalid + if all(b == 0 for b in self.memory_read(xcpregs, regsize)): + self.logger.error( + f"Invalid g_last_regs: @ {xcpregs:#x}, use TCB instead" + ) + xcpregs = None + else: + print( + f"\x1b[31;1mLoad CPU{cpu} task [{name}] registers from g_last_regs\x1b[m" + ) + + if not xcpregs: + off = tcbinfo.regs_off + xcpregs = data[off : off + pointer.sizeof()] + xcpregs = pointer.parse(xcpregs) try: registers.load(addr=xcpregs) -- Gitee From 5fc5472ede7e38517f1c0869ada98046df6a300c Mon Sep 17 00:00:00 2001 From: wangmingrong1 Date: Wed, 16 Apr 2025 19:56:28 +0800 Subject: [PATCH 207/235] gdb diagnose report: Supports filtering and running only certain commands VELAPLATFO-59181 Change-Id: Ia3125b8ba109973a7b7ba82e5e4bd75bdac78633 Signed-off-by: wangmingrong1 --- tools/pynuttx/nxgdb/diagnose.py | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/tools/pynuttx/nxgdb/diagnose.py b/tools/pynuttx/nxgdb/diagnose.py index 54391550a85..a5c598b6952 100644 --- a/tools/pynuttx/nxgdb/diagnose.py +++ b/tools/pynuttx/nxgdb/diagnose.py @@ -50,6 +50,15 @@ class DiagnoseReport(gdb.Command): type=str, help="report output file name", ) + parser.add_argument( + "-c", + "--command", + nargs="+", + help="only run specified commands (case-insensitive)", + ) + parser.add_argument( + "-l", "--list", action="store_true", help="list available commands" + ) try: args = parser.parse_args(gdb.string_to_argv(args)) @@ -74,6 +83,8 @@ class DiagnoseReport(gdb.Command): if isinstance(obj, cls) and not isinstance(obj, type) } + only_set = set(name.lower() for name in args.command) if args.command else None + results = [] for clz in commands: if hasattr(clz, "diagnose"): @@ -81,6 +92,15 @@ class DiagnoseReport(gdb.Command): name = clz.__name__.lower() if name not in registered_command_types: continue + + if args.list: + gdb.write(f"{name}\n") + continue + + if only_set: + if name not in only_set: + continue + gdb.write(f"Run command: {name}\n") try: result = command.diagnose() @@ -98,6 +118,9 @@ class DiagnoseReport(gdb.Command): result.setdefault("command", name) results.append(result) + if args.list: + return + gdb.write(f"Write report to {reportfile}\n") with open(reportfile, "w") as f: f.write(utils.jsonify(results, indent=4)) -- Gitee From 4d492df3293720ded41da627d74c8ef6b327df2d Mon Sep 17 00:00:00 2001 From: wangmingrong1 Date: Fri, 21 Mar 2025 16:17:17 +0800 Subject: [PATCH 208/235] Make stack-usage display better VELAPLATFO-59181 Pid | Name | Entry | Base | Size | CurUsage | MaxUsage 0 | Idle_Task | 0x60001c05 | 0x21025058 | 4016 | 104 -> 2.59% | 756 -> 18.82% 1 | hpwork | 0x60004339 | 0x21009cc0 | 1920 | 136 -> 7.08% | 360 -> 18.75% 2 | lpwork | 0x60004339 | 0x210094c0 | 1920 | 136 -> 7.08% | 360 -> 18.75% 4 | vnc_server | 0x60037af5 | 0x210470b0 | 1936 | 320 -> 16.53% | 544 -> 28.10% Change-Id: I9dae720e7a6691049c17f372e76c0cd76a96b211 Signed-off-by: wangmingrong1 --- tools/pynuttx/nxgdb/stack.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tools/pynuttx/nxgdb/stack.py b/tools/pynuttx/nxgdb/stack.py index 1c0e946f535..312b27ba080 100644 --- a/tools/pynuttx/nxgdb/stack.py +++ b/tools/pynuttx/nxgdb/stack.py @@ -174,13 +174,13 @@ class StackUsage(gdb.Command): self._stacks = [] # format template self._fmt = ( - "{0: <4} | {1: <10} | {2: <10} | {3: <20} | {4: <10} | {5: <10} | {6: <10}" + "{0: <4} | {1: <10} | {2: <10} | {3: <20} | {4: <10} | {5: <15} | {6: <15}" ) def format_print(self, pid, stack): def gen_info_str(x): usage = x / stack._stack_size - res = ",".join([str(x), "{0:.2%}".format(usage)]) + res = f"{str(x)} -> {usage:.2%}" if usage > 0.8: res += "!" return res -- Gitee From 45246d697f1c0e6b4ded4dbceb81d2b7ab01ff3c Mon Sep 17 00:00:00 2001 From: wangmingrong1 Date: Fri, 18 Apr 2025 11:43:34 +0800 Subject: [PATCH 209/235] gdb plugin: Adjust sem_is_mutex api parameter passing VELAPLATFO-59181 Change-Id: Ib724575f999368ae5a134c3047e734ded5f79f64 Signed-off-by: wangmingrong1 --- tools/pynuttx/nxgdb/nxcrash/deadlock.py | 2 +- tools/pynuttx/nxgdb/thread.py | 5 ++--- tools/pynuttx/nxgdb/utils.py | 3 ++- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/tools/pynuttx/nxgdb/nxcrash/deadlock.py b/tools/pynuttx/nxgdb/nxcrash/deadlock.py index 945fd26b3b8..2c02b55917c 100644 --- a/tools/pynuttx/nxgdb/nxcrash/deadlock.py +++ b/tools/pynuttx/nxgdb/nxcrash/deadlock.py @@ -40,7 +40,7 @@ class DeadLock(gdb.Command): return False sem = tcb["waitobj"].cast(utils.lookup_type("sem_t").pointer()) - if not utils.sem_is_mutex(sem["flags"]): + if not utils.sem_is_mutex(sem): return False # It's waiting on a mutex diff --git a/tools/pynuttx/nxgdb/thread.py b/tools/pynuttx/nxgdb/thread.py index b588d04021a..1464fb60521 100644 --- a/tools/pynuttx/nxgdb/thread.py +++ b/tools/pynuttx/nxgdb/thread.py @@ -225,7 +225,7 @@ class Nxinfothreads(gdb.Command): if tcb["task_state"] == gdb.parse_and_eval("TSTATE_WAIT_SEM"): mutex = tcb["waitobj"].cast(utils.lookup_type("sem_t").pointer()) - if utils.sem_is_mutex(mutex["flags"]): + if utils.sem_is_mutex(mutex): mutex = tcb["waitobj"].cast(utils.lookup_type("mutex_t").pointer()) statename = f"Waiting,Mutex:{mutex['holder']}" @@ -459,8 +459,7 @@ class Ps(gdb.Command): waiter = ( str(int(cast2ptr(tcb["waitobj"], "mutex_t")["holder"])) - if tcb["waitobj"] - and utils.sem_is_mutex(cast2ptr(tcb["waitobj"], "sem_t")["flags"]) + if tcb["waitobj"] and utils.sem_is_mutex(cast2ptr(tcb["waitobj"], "sem_t")) else "" ) state_and_event = eval2str(TaskState, (tcb["task_state"])) + ( diff --git a/tools/pynuttx/nxgdb/utils.py b/tools/pynuttx/nxgdb/utils.py index 84ae86e2672..e54a60049bc 100644 --- a/tools/pynuttx/nxgdb/utils.py +++ b/tools/pynuttx/nxgdb/utils.py @@ -974,7 +974,8 @@ def task_is_idle(tcb): # sem def sem_is_mutex(sem): - return sem & get_symbol_value("SEM_TYPE_MUTEX") + SEM_TYPE_MUTEX = 4 + return sem["flags"] & SEM_TYPE_MUTEX def switch_inferior(inferior): -- Gitee From 164a741754ae0382326cff3bf0f34401ad1199f9 Mon Sep 17 00:00:00 2001 From: xuxingliang Date: Mon, 27 Jan 2025 16:40:45 +0800 Subject: [PATCH 210/235] arch: add register name/size to reginfo VELAPLATFO-53264 These details are crucial for building a fully functional GDB stub. Additionally, this enhancement simplifies the implementation of gdbserver.py located in the tools/ directory. The inclusion of register names specifically aids in matching the registers requested by GDB with those available in the TCB, streamlining the debugging process. Change-Id: I2498cf13056851902204aa9a2fc9242610ef1503 Signed-off-by: xuxingliang --- arch/arm/src/arm/arm_tcbinfo.c | 44 ++++---- arch/arm/src/armv6-m/arm_tcbinfo.c | 52 ++++----- arch/arm/src/armv7-a/arm_tcbinfo.c | 113 ++++---------------- arch/arm/src/armv7-m/arm_tcbinfo.c | 94 ++++------------ arch/arm/src/armv7-r/arm_tcbinfo.c | 88 ++++----------- arch/arm/src/armv8-m/arm_tcbinfo.c | 94 ++++------------ arch/arm/src/armv8-r/arm_tcbinfo.c | 102 ++++++------------ arch/arm64/src/common/arm64_tcbinfo.c | 78 +++++++------- arch/risc-v/src/common/riscv_tcbinfo.c | 116 +++++++------------- arch/sim/src/sim/sim_tcbinfo.c | 124 +++++----------------- arch/sparc/src/common/sparc_tcbinfo.c | 74 ++++++------- arch/tricore/src/common/tricore_tcbinfo.c | 8 +- arch/x86/src/common/x86_tcbinfo.c | 36 +++---- arch/x86_64/src/common/x86_64_tcbinfo.c | 58 +++++----- arch/xtensa/src/common/xtensa_tcbinfo.c | 42 ++++---- include/nuttx/sched.h | 36 ++++--- 16 files changed, 413 insertions(+), 746 deletions(-) diff --git a/arch/arm/src/arm/arm_tcbinfo.c b/arch/arm/src/arm/arm_tcbinfo.c index 1d2cfd6f6cc..77f2f0be459 100644 --- a/arch/arm/src/arm/arm_tcbinfo.c +++ b/arch/arm/src/arm/arm_tcbinfo.c @@ -32,25 +32,27 @@ * Private Data ****************************************************************************/ -static const uint16_t g_reg_offs[] = +/* Name, Size, Regnum, TCB offset, g/G offset */ + +static const struct reginfo_s g_reginfo[] = { - TCB_REG_OFF(REG_R0), - TCB_REG_OFF(REG_R1), - TCB_REG_OFF(REG_R2), - TCB_REG_OFF(REG_R3), - TCB_REG_OFF(REG_R4), - TCB_REG_OFF(REG_R5), - TCB_REG_OFF(REG_R6), - TCB_REG_OFF(REG_R7), - TCB_REG_OFF(REG_R8), - TCB_REG_OFF(REG_R9), - TCB_REG_OFF(REG_R10), - TCB_REG_OFF(REG_R11), - TCB_REG_OFF(REG_R12), - TCB_REG_OFF(REG_R13), - TCB_REG_OFF(REG_R14), - TCB_REG_OFF(REG_R15), - TCB_REG_OFF(REG_CPSR), + {"r0", 4, 0, TCB_REG_OFF(REG_R0), REGINFO_OFFSET_AUTO}, + {"r1", 4, 1, TCB_REG_OFF(REG_R1), REGINFO_OFFSET_AUTO}, + {"r2", 4, 2, TCB_REG_OFF(REG_R2), REGINFO_OFFSET_AUTO}, + {"r3", 4, 3, TCB_REG_OFF(REG_R3), REGINFO_OFFSET_AUTO}, + {"r4", 4, 4, TCB_REG_OFF(REG_R4), REGINFO_OFFSET_AUTO}, + {"r5", 4, 5, TCB_REG_OFF(REG_R5), REGINFO_OFFSET_AUTO}, + {"r6", 4, 6, TCB_REG_OFF(REG_R6), REGINFO_OFFSET_AUTO}, + {"r7", 4, 7, TCB_REG_OFF(REG_R7), REGINFO_OFFSET_AUTO}, + {"r8", 4, 8, TCB_REG_OFF(REG_R8), REGINFO_OFFSET_AUTO}, + {"r9", 4, 9, TCB_REG_OFF(REG_R9), REGINFO_OFFSET_AUTO}, + {"r10", 4, 10, TCB_REG_OFF(REG_R10), REGINFO_OFFSET_AUTO}, + {"r11", 4, 11, TCB_REG_OFF(REG_R11), REGINFO_OFFSET_AUTO}, + {"r12", 4, 12, TCB_REG_OFF(REG_R12), REGINFO_OFFSET_AUTO}, + {"sp", 4, 13, TCB_REG_OFF(REG_R13), REGINFO_OFFSET_AUTO}, + {"lr", 4, 14, TCB_REG_OFF(REG_R14), REGINFO_OFFSET_AUTO}, + {"pc", 4, 15, TCB_REG_OFF(REG_R15), REGINFO_OFFSET_AUTO}, + {"cpsr", 4, 25, TCB_REG_OFF(REG_CPSR), REGINFO_OFFSET_AUTO}, }; /**************************************************************************** @@ -66,10 +68,10 @@ const struct tcbinfo_s g_tcbinfo used_data = .stack_off = TCB_STACK_OFF, .stack_size_off = TCB_STACK_SIZE_OFF, .regs_off = TCB_REGS_OFF, - .regs_num = nitems(g_reg_offs), + .regs_num = nitems(g_reginfo), { - .p = g_reg_offs, - }, + .reginfo = g_reginfo, + } }; /**************************************************************************** diff --git a/arch/arm/src/armv6-m/arm_tcbinfo.c b/arch/arm/src/armv6-m/arm_tcbinfo.c index d89968c22a8..f88aa94b4e4 100644 --- a/arch/arm/src/armv6-m/arm_tcbinfo.c +++ b/arch/arm/src/armv6-m/arm_tcbinfo.c @@ -32,33 +32,27 @@ * Private Data ****************************************************************************/ -static const uint16_t g_reg_offs[] = +/* Name, Size, Regnum, TCB offset, g/G offset */ + +static const struct reginfo_s g_reginfo[] = { - TCB_REG_OFF(REG_R0), - TCB_REG_OFF(REG_R1), - TCB_REG_OFF(REG_R2), - TCB_REG_OFF(REG_R3), - TCB_REG_OFF(REG_R4), - TCB_REG_OFF(REG_R5), - TCB_REG_OFF(REG_R6), - TCB_REG_OFF(REG_R7), - TCB_REG_OFF(REG_R8), - TCB_REG_OFF(REG_R9), - TCB_REG_OFF(REG_R10), - TCB_REG_OFF(REG_R11), - TCB_REG_OFF(REG_R12), - TCB_REG_OFF(REG_R13), - TCB_REG_OFF(REG_R14), - TCB_REG_OFF(REG_R15), - TCB_REG_OFF(REG_XPSR), -#if 0 - UINT16_MAX, /* msp */ - TCB_REG_OFF(REG_R13), - TCB_REG_OFF(REG_PRIMASK), - UINT16_MAX, /* basepri */ - UINT16_MAX, /* faultmask */ - UINT16_MAX, /* control */ -#endif + {"r0", 4, 0, TCB_REG_OFF(REG_R0), REGINFO_OFFSET_AUTO}, + {"r1", 4, 1, TCB_REG_OFF(REG_R1), REGINFO_OFFSET_AUTO}, + {"r2", 4, 2, TCB_REG_OFF(REG_R2), REGINFO_OFFSET_AUTO}, + {"r3", 4, 3, TCB_REG_OFF(REG_R3), REGINFO_OFFSET_AUTO}, + {"r4", 4, 4, TCB_REG_OFF(REG_R4), REGINFO_OFFSET_AUTO}, + {"r5", 4, 5, TCB_REG_OFF(REG_R5), REGINFO_OFFSET_AUTO}, + {"r6", 4, 6, TCB_REG_OFF(REG_R6), REGINFO_OFFSET_AUTO}, + {"r7", 4, 7, TCB_REG_OFF(REG_R7), REGINFO_OFFSET_AUTO}, + {"r8", 4, 8, TCB_REG_OFF(REG_R8), REGINFO_OFFSET_AUTO}, + {"r9", 4, 9, TCB_REG_OFF(REG_R9), REGINFO_OFFSET_AUTO}, + {"r10", 4, 10, TCB_REG_OFF(REG_R10), REGINFO_OFFSET_AUTO}, + {"r11", 4, 11, TCB_REG_OFF(REG_R11), REGINFO_OFFSET_AUTO}, + {"r12", 4, 12, TCB_REG_OFF(REG_R12), REGINFO_OFFSET_AUTO}, + {"sp", 4, 13, TCB_REG_OFF(REG_R13), REGINFO_OFFSET_AUTO}, + {"lr", 4, 14, TCB_REG_OFF(REG_R14), REGINFO_OFFSET_AUTO}, + {"pc", 4, 15, TCB_REG_OFF(REG_R15), REGINFO_OFFSET_AUTO}, + {"xpsr", 4, 25, TCB_REG_OFF(REG_XPSR), REGINFO_OFFSET_AUTO}, }; /**************************************************************************** @@ -74,10 +68,10 @@ const struct tcbinfo_s g_tcbinfo used_data = .stack_off = TCB_STACK_OFF, .stack_size_off = TCB_STACK_SIZE_OFF, .regs_off = TCB_REGS_OFF, - .regs_num = nitems(g_reg_offs), + .regs_num = nitems(g_reginfo), { - .p = g_reg_offs, - }, + .reginfo = g_reginfo, + } }; /**************************************************************************** diff --git a/arch/arm/src/armv7-a/arm_tcbinfo.c b/arch/arm/src/armv7-a/arm_tcbinfo.c index ecc79962f53..dc82bfa2433 100644 --- a/arch/arm/src/armv7-a/arm_tcbinfo.c +++ b/arch/arm/src/armv7-a/arm_tcbinfo.c @@ -32,94 +32,27 @@ * Private Data ****************************************************************************/ -static const uint16_t g_reg_offs[] = -{ - TCB_REG_OFF(REG_R0), /* 0 */ - TCB_REG_OFF(REG_R1), /* 1 */ - TCB_REG_OFF(REG_R2), /* 2 */ - TCB_REG_OFF(REG_R3), /* 3 */ - TCB_REG_OFF(REG_R4), /* 4 */ - TCB_REG_OFF(REG_R5), /* 5 */ - TCB_REG_OFF(REG_R6), /* 6 */ - TCB_REG_OFF(REG_R7), /* 7 */ - TCB_REG_OFF(REG_R8), /* 8 */ - TCB_REG_OFF(REG_R9), /* 9 */ - TCB_REG_OFF(REG_R10), /* 10 */ - TCB_REG_OFF(REG_R11), /* 11 */ - TCB_REG_OFF(REG_R12), /* 12 */ - TCB_REG_OFF(REG_R13), /* 13 */ - TCB_REG_OFF(REG_R14), /* 14 */ - TCB_REG_OFF(REG_R15), /* 15 */ - UINT16_MAX, /* 16 */ - UINT16_MAX, /* 17 */ - UINT16_MAX, /* 18 */ - UINT16_MAX, /* 19 */ - UINT16_MAX, /* 20 */ - UINT16_MAX, /* 21 */ - UINT16_MAX, /* 22 */ - UINT16_MAX, /* 23 */ - UINT16_MAX, /* 24 */ - UINT16_MAX, /* 25 */ - UINT16_MAX, /* 26 */ - UINT16_MAX, /* 27 */ - UINT16_MAX, /* 28 */ - UINT16_MAX, /* 29 */ - UINT16_MAX, /* 30 */ - UINT16_MAX, /* 31 */ - UINT16_MAX, /* 32 */ - UINT16_MAX, /* 33 */ - UINT16_MAX, /* 34 */ - UINT16_MAX, /* 35 */ - UINT16_MAX, /* 36 */ - UINT16_MAX, /* 37 */ - UINT16_MAX, /* 38 */ - UINT16_MAX, /* 39 */ - UINT16_MAX, /* 40 */ - TCB_REG_OFF(REG_CPSR), /* 41 */ - -#if 0 -# ifdef CONFIG_ARCH_FPU - TCB_REG_OFF(REG_D0), - TCB_REG_OFF(REG_D1), - TCB_REG_OFF(REG_D2), - TCB_REG_OFF(REG_D3), - TCB_REG_OFF(REG_D4), - TCB_REG_OFF(REG_D5), - TCB_REG_OFF(REG_D6), - TCB_REG_OFF(REG_D7), - TCB_REG_OFF(REG_D8), - TCB_REG_OFF(REG_D9), - TCB_REG_OFF(REG_D10), - TCB_REG_OFF(REG_D11), - TCB_REG_OFF(REG_D12), - TCB_REG_OFF(REG_D13), - TCB_REG_OFF(REG_D14), - TCB_REG_OFF(REG_D15), -# endif +/* Name, Size, Regnum, TCB offset, g/G offset */ -# ifdef CONFIG_ARM_DPFPU32 - TCB_REG_OFF(REG_D16), - TCB_REG_OFF(REG_D17), - TCB_REG_OFF(REG_D18), - TCB_REG_OFF(REG_D19), - TCB_REG_OFF(REG_D20), - TCB_REG_OFF(REG_D21), - TCB_REG_OFF(REG_D22), - TCB_REG_OFF(REG_D23), - TCB_REG_OFF(REG_D24), - TCB_REG_OFF(REG_D25), - TCB_REG_OFF(REG_D26), - TCB_REG_OFF(REG_D27), - TCB_REG_OFF(REG_D28), - TCB_REG_OFF(REG_D29), - TCB_REG_OFF(REG_D30), - TCB_REG_OFF(REG_D31), -# endif - -# ifdef CONFIG_ARCH_FPU - TCB_REG_OFF(REG_FPSCR), -# endif -#endif +static const struct reginfo_s g_reginfo[] = +{ + {"r0", 4, 0, TCB_REG_OFF(REG_R0), REGINFO_OFFSET_AUTO}, + {"r1", 4, 1, TCB_REG_OFF(REG_R1), REGINFO_OFFSET_AUTO}, + {"r2", 4, 2, TCB_REG_OFF(REG_R2), REGINFO_OFFSET_AUTO}, + {"r3", 4, 3, TCB_REG_OFF(REG_R3), REGINFO_OFFSET_AUTO}, + {"r4", 4, 4, TCB_REG_OFF(REG_R4), REGINFO_OFFSET_AUTO}, + {"r5", 4, 5, TCB_REG_OFF(REG_R5), REGINFO_OFFSET_AUTO}, + {"r6", 4, 6, TCB_REG_OFF(REG_R6), REGINFO_OFFSET_AUTO}, + {"r7", 4, 7, TCB_REG_OFF(REG_R7), REGINFO_OFFSET_AUTO}, + {"r8", 4, 8, TCB_REG_OFF(REG_R8), REGINFO_OFFSET_AUTO}, + {"r9", 4, 9, TCB_REG_OFF(REG_R9), REGINFO_OFFSET_AUTO}, + {"r10", 4, 10, TCB_REG_OFF(REG_R10), REGINFO_OFFSET_AUTO}, + {"r11", 4, 11, TCB_REG_OFF(REG_R11), REGINFO_OFFSET_AUTO}, + {"r12", 4, 12, TCB_REG_OFF(REG_R12), REGINFO_OFFSET_AUTO}, + {"sp", 4, 13, TCB_REG_OFF(REG_R13), REGINFO_OFFSET_AUTO}, + {"lr", 4, 14, TCB_REG_OFF(REG_R14), REGINFO_OFFSET_AUTO}, + {"pc", 4, 15, TCB_REG_OFF(REG_R15), REGINFO_OFFSET_AUTO}, + {"cpsr", 4, 25, TCB_REG_OFF(REG_CPSR), REGINFO_OFFSET_AUTO}, }; /**************************************************************************** @@ -135,10 +68,10 @@ const struct tcbinfo_s g_tcbinfo used_data = .stack_off = TCB_STACK_OFF, .stack_size_off = TCB_STACK_SIZE_OFF, .regs_off = TCB_REGS_OFF, - .regs_num = nitems(g_reg_offs), + .regs_num = nitems(g_reginfo), { - .p = g_reg_offs, - }, + .reginfo = g_reginfo, + } }; /**************************************************************************** diff --git a/arch/arm/src/armv7-m/arm_tcbinfo.c b/arch/arm/src/armv7-m/arm_tcbinfo.c index 1da31a52d48..cb9eed38a79 100644 --- a/arch/arm/src/armv7-m/arm_tcbinfo.c +++ b/arch/arm/src/armv7-m/arm_tcbinfo.c @@ -32,75 +32,27 @@ * Private Data ****************************************************************************/ -static const uint16_t g_reg_offs[] = -{ - TCB_REG_OFF(REG_R0), - TCB_REG_OFF(REG_R1), - TCB_REG_OFF(REG_R2), - TCB_REG_OFF(REG_R3), - TCB_REG_OFF(REG_R4), - TCB_REG_OFF(REG_R5), - TCB_REG_OFF(REG_R6), - TCB_REG_OFF(REG_R7), - TCB_REG_OFF(REG_R8), - TCB_REG_OFF(REG_R9), - TCB_REG_OFF(REG_R10), - TCB_REG_OFF(REG_R11), - TCB_REG_OFF(REG_R12), - TCB_REG_OFF(REG_R13), - TCB_REG_OFF(REG_R14), - TCB_REG_OFF(REG_R15), - TCB_REG_OFF(REG_XPSR), - -#if 0 - UINT16_MAX, /* msp */ - TCB_REG_OFF(REG_R13), -# ifdef CONFIG_ARMV7M_USEBASEPRI - UINT16_MAX, /* primask */ - TCB_REG_OFF(REG_BASEPRI), -# else - TCB_REG_OFF(REG_PRIMASK), - UINT16_MAX, /* basepri */ -# endif - UINT16_MAX, /* faultmask */ - UINT16_MAX, /* control */ +/* Name, Size, Regnum, TCB offset, g/G offset */ -# ifdef CONFIG_ARCH_FPU - TCB_REG_OFF(REG_S0), - TCB_REG_OFF(REG_S1), - TCB_REG_OFF(REG_S2), - TCB_REG_OFF(REG_S3), - TCB_REG_OFF(REG_S4), - TCB_REG_OFF(REG_S5), - TCB_REG_OFF(REG_S6), - TCB_REG_OFF(REG_S7), - TCB_REG_OFF(REG_S8), - TCB_REG_OFF(REG_S9), - TCB_REG_OFF(REG_S10), - TCB_REG_OFF(REG_S11), - TCB_REG_OFF(REG_S12), - TCB_REG_OFF(REG_S13), - TCB_REG_OFF(REG_S14), - TCB_REG_OFF(REG_S15), - TCB_REG_OFF(REG_S16), - TCB_REG_OFF(REG_S17), - TCB_REG_OFF(REG_S18), - TCB_REG_OFF(REG_S19), - TCB_REG_OFF(REG_S20), - TCB_REG_OFF(REG_S21), - TCB_REG_OFF(REG_S22), - TCB_REG_OFF(REG_S23), - TCB_REG_OFF(REG_S24), - TCB_REG_OFF(REG_S25), - TCB_REG_OFF(REG_S26), - TCB_REG_OFF(REG_S27), - TCB_REG_OFF(REG_S28), - TCB_REG_OFF(REG_S29), - TCB_REG_OFF(REG_S30), - TCB_REG_OFF(REG_S31), - TCB_REG_OFF(REG_FPSCR), -# endif -#endif +static const struct reginfo_s g_reginfo[] = +{ + {"r0", 4, 0, TCB_REG_OFF(REG_R0), REGINFO_OFFSET_AUTO}, + {"r1", 4, 1, TCB_REG_OFF(REG_R1), REGINFO_OFFSET_AUTO}, + {"r2", 4, 2, TCB_REG_OFF(REG_R2), REGINFO_OFFSET_AUTO}, + {"r3", 4, 3, TCB_REG_OFF(REG_R3), REGINFO_OFFSET_AUTO}, + {"r4", 4, 4, TCB_REG_OFF(REG_R4), REGINFO_OFFSET_AUTO}, + {"r5", 4, 5, TCB_REG_OFF(REG_R5), REGINFO_OFFSET_AUTO}, + {"r6", 4, 6, TCB_REG_OFF(REG_R6), REGINFO_OFFSET_AUTO}, + {"r7", 4, 7, TCB_REG_OFF(REG_R7), REGINFO_OFFSET_AUTO}, + {"r8", 4, 8, TCB_REG_OFF(REG_R8), REGINFO_OFFSET_AUTO}, + {"r9", 4, 9, TCB_REG_OFF(REG_R9), REGINFO_OFFSET_AUTO}, + {"r10", 4, 10, TCB_REG_OFF(REG_R10), REGINFO_OFFSET_AUTO}, + {"r11", 4, 11, TCB_REG_OFF(REG_R11), REGINFO_OFFSET_AUTO}, + {"r12", 4, 12, TCB_REG_OFF(REG_R12), REGINFO_OFFSET_AUTO}, + {"sp", 4, 13, TCB_REG_OFF(REG_R13), REGINFO_OFFSET_AUTO}, + {"lr", 4, 14, TCB_REG_OFF(REG_R14), REGINFO_OFFSET_AUTO}, + {"pc", 4, 15, TCB_REG_OFF(REG_R15), REGINFO_OFFSET_AUTO}, + {"xpsr", 4, 25, TCB_REG_OFF(REG_XPSR), REGINFO_OFFSET_AUTO}, }; /**************************************************************************** @@ -116,10 +68,10 @@ const struct tcbinfo_s g_tcbinfo used_data = .stack_off = TCB_STACK_OFF, .stack_size_off = TCB_STACK_SIZE_OFF, .regs_off = TCB_REGS_OFF, - .regs_num = nitems(g_reg_offs), + .regs_num = nitems(g_reginfo), { - .p = g_reg_offs, - }, + .reginfo = g_reginfo, + } }; /**************************************************************************** diff --git a/arch/arm/src/armv7-r/arm_tcbinfo.c b/arch/arm/src/armv7-r/arm_tcbinfo.c index 0e78e540d86..0b354fcb59d 100644 --- a/arch/arm/src/armv7-r/arm_tcbinfo.c +++ b/arch/arm/src/armv7-r/arm_tcbinfo.c @@ -32,69 +32,27 @@ * Private Data ****************************************************************************/ -static const uint16_t g_reg_offs[] = -{ - TCB_REG_OFF(REG_R0), - TCB_REG_OFF(REG_R1), - TCB_REG_OFF(REG_R2), - TCB_REG_OFF(REG_R3), - TCB_REG_OFF(REG_R4), - TCB_REG_OFF(REG_R5), - TCB_REG_OFF(REG_R6), - TCB_REG_OFF(REG_R7), - TCB_REG_OFF(REG_R8), - TCB_REG_OFF(REG_R9), - TCB_REG_OFF(REG_R10), - TCB_REG_OFF(REG_R11), - TCB_REG_OFF(REG_R12), - TCB_REG_OFF(REG_R13), - TCB_REG_OFF(REG_R14), - TCB_REG_OFF(REG_R15), - TCB_REG_OFF(REG_CPSR), - -#if 0 -# ifdef CONFIG_ARCH_FPU - TCB_REG_OFF(REG_D0), - TCB_REG_OFF(REG_D1), - TCB_REG_OFF(REG_D2), - TCB_REG_OFF(REG_D3), - TCB_REG_OFF(REG_D4), - TCB_REG_OFF(REG_D5), - TCB_REG_OFF(REG_D6), - TCB_REG_OFF(REG_D7), - TCB_REG_OFF(REG_D8), - TCB_REG_OFF(REG_D9), - TCB_REG_OFF(REG_D10), - TCB_REG_OFF(REG_D11), - TCB_REG_OFF(REG_D12), - TCB_REG_OFF(REG_D13), - TCB_REG_OFF(REG_D14), - TCB_REG_OFF(REG_D15), -# endif +/* Name, Size, Regnum, TCB offset, g/G offset */ -# ifdef CONFIG_ARM_DPFPU32 - TCB_REG_OFF(REG_D16), - TCB_REG_OFF(REG_D17), - TCB_REG_OFF(REG_D18), - TCB_REG_OFF(REG_D19), - TCB_REG_OFF(REG_D20), - TCB_REG_OFF(REG_D21), - TCB_REG_OFF(REG_D22), - TCB_REG_OFF(REG_D23), - TCB_REG_OFF(REG_D24), - TCB_REG_OFF(REG_D25), - TCB_REG_OFF(REG_D26), - TCB_REG_OFF(REG_D27), - TCB_REG_OFF(REG_D28), - TCB_REG_OFF(REG_D29), - TCB_REG_OFF(REG_D30), - TCB_REG_OFF(REG_D31), -# endif - -# ifdef CONFIG_ARCH_FPU - TCB_REG_OFF(REG_FPSCR), -# endif -#endif +static const struct reginfo_s g_reginfo[] = +{ + {"r0", 4, 0, TCB_REG_OFF(REG_R0), REGINFO_OFFSET_AUTO}, + {"r1", 4, 1, TCB_REG_OFF(REG_R1), REGINFO_OFFSET_AUTO}, + {"r2", 4, 2, TCB_REG_OFF(REG_R2), REGINFO_OFFSET_AUTO}, + {"r3", 4, 3, TCB_REG_OFF(REG_R3), REGINFO_OFFSET_AUTO}, + {"r4", 4, 4, TCB_REG_OFF(REG_R4), REGINFO_OFFSET_AUTO}, + {"r5", 4, 5, TCB_REG_OFF(REG_R5), REGINFO_OFFSET_AUTO}, + {"r6", 4, 6, TCB_REG_OFF(REG_R6), REGINFO_OFFSET_AUTO}, + {"r7", 4, 7, TCB_REG_OFF(REG_R7), REGINFO_OFFSET_AUTO}, + {"r8", 4, 8, TCB_REG_OFF(REG_R8), REGINFO_OFFSET_AUTO}, + {"r9", 4, 9, TCB_REG_OFF(REG_R9), REGINFO_OFFSET_AUTO}, + {"r10", 4, 10, TCB_REG_OFF(REG_R10), REGINFO_OFFSET_AUTO}, + {"r11", 4, 11, TCB_REG_OFF(REG_R11), REGINFO_OFFSET_AUTO}, + {"r12", 4, 12, TCB_REG_OFF(REG_R12), REGINFO_OFFSET_AUTO}, + {"sp", 4, 13, TCB_REG_OFF(REG_R13), REGINFO_OFFSET_AUTO}, + {"lr", 4, 14, TCB_REG_OFF(REG_R14), REGINFO_OFFSET_AUTO}, + {"pc", 4, 15, TCB_REG_OFF(REG_R15), REGINFO_OFFSET_AUTO}, + {"cpsr", 4, 25, TCB_REG_OFF(REG_XPSR), REGINFO_OFFSET_AUTO}, }; /**************************************************************************** @@ -110,10 +68,10 @@ const struct tcbinfo_s g_tcbinfo used_data = .stack_off = TCB_STACK_OFF, .stack_size_off = TCB_STACK_SIZE_OFF, .regs_off = TCB_REGS_OFF, - .regs_num = nitems(g_reg_offs), + .regs_num = nitems(g_reginfo), { - .p = g_reg_offs, - }, + .reginfo = g_reginfo, + } }; /**************************************************************************** diff --git a/arch/arm/src/armv8-m/arm_tcbinfo.c b/arch/arm/src/armv8-m/arm_tcbinfo.c index 3027e4bf3c2..6dfc2518a46 100644 --- a/arch/arm/src/armv8-m/arm_tcbinfo.c +++ b/arch/arm/src/armv8-m/arm_tcbinfo.c @@ -32,75 +32,27 @@ * Private Data ****************************************************************************/ -static const uint16_t g_reg_offs[] = -{ - TCB_REG_OFF(REG_R0), - TCB_REG_OFF(REG_R1), - TCB_REG_OFF(REG_R2), - TCB_REG_OFF(REG_R3), - TCB_REG_OFF(REG_R4), - TCB_REG_OFF(REG_R5), - TCB_REG_OFF(REG_R6), - TCB_REG_OFF(REG_R7), - TCB_REG_OFF(REG_R8), - TCB_REG_OFF(REG_R9), - TCB_REG_OFF(REG_R10), - TCB_REG_OFF(REG_R11), - TCB_REG_OFF(REG_R12), - TCB_REG_OFF(REG_R13), - TCB_REG_OFF(REG_R14), - TCB_REG_OFF(REG_R15), - TCB_REG_OFF(REG_XPSR), - -#if 0 - UINT16_MAX, /* msp */ - TCB_REG_OFF(REG_R13), -# ifdef CONFIG_ARMV8M_USEBASEPRI - UINT16_MAX, /* primask */ - TCB_REG_OFF(REG_BASEPRI), -# else - TCB_REG_OFF(REG_PRIMASK), - UINT16_MAX, /* basepri */ -# endif - UINT16_MAX, /* faultmask */ - UINT16_MAX, /* control */ +/* Name, Size, Regnum, TCB offset, g/G offset */ -# ifdef CONFIG_ARCH_FPU - TCB_REG_OFF(REG_S0), - TCB_REG_OFF(REG_S1), - TCB_REG_OFF(REG_S2), - TCB_REG_OFF(REG_S3), - TCB_REG_OFF(REG_S4), - TCB_REG_OFF(REG_S5), - TCB_REG_OFF(REG_S6), - TCB_REG_OFF(REG_S7), - TCB_REG_OFF(REG_S8), - TCB_REG_OFF(REG_S9), - TCB_REG_OFF(REG_S10), - TCB_REG_OFF(REG_S11), - TCB_REG_OFF(REG_S12), - TCB_REG_OFF(REG_S13), - TCB_REG_OFF(REG_S14), - TCB_REG_OFF(REG_S15), - TCB_REG_OFF(REG_S16), - TCB_REG_OFF(REG_S17), - TCB_REG_OFF(REG_S18), - TCB_REG_OFF(REG_S19), - TCB_REG_OFF(REG_S20), - TCB_REG_OFF(REG_S21), - TCB_REG_OFF(REG_S22), - TCB_REG_OFF(REG_S23), - TCB_REG_OFF(REG_S24), - TCB_REG_OFF(REG_S25), - TCB_REG_OFF(REG_S26), - TCB_REG_OFF(REG_S27), - TCB_REG_OFF(REG_S28), - TCB_REG_OFF(REG_S29), - TCB_REG_OFF(REG_S30), - TCB_REG_OFF(REG_S31), - TCB_REG_OFF(REG_FPSCR), -# endif -#endif +static const struct reginfo_s g_reginfo[] = +{ + {"r0", 4, 0, TCB_REG_OFF(REG_R0), REGINFO_OFFSET_AUTO}, + {"r1", 4, 1, TCB_REG_OFF(REG_R1), REGINFO_OFFSET_AUTO}, + {"r2", 4, 2, TCB_REG_OFF(REG_R2), REGINFO_OFFSET_AUTO}, + {"r3", 4, 3, TCB_REG_OFF(REG_R3), REGINFO_OFFSET_AUTO}, + {"r4", 4, 4, TCB_REG_OFF(REG_R4), REGINFO_OFFSET_AUTO}, + {"r5", 4, 5, TCB_REG_OFF(REG_R5), REGINFO_OFFSET_AUTO}, + {"r6", 4, 6, TCB_REG_OFF(REG_R6), REGINFO_OFFSET_AUTO}, + {"r7", 4, 7, TCB_REG_OFF(REG_R7), REGINFO_OFFSET_AUTO}, + {"r8", 4, 8, TCB_REG_OFF(REG_R8), REGINFO_OFFSET_AUTO}, + {"r9", 4, 9, TCB_REG_OFF(REG_R9), REGINFO_OFFSET_AUTO}, + {"r10", 4, 10, TCB_REG_OFF(REG_R10), REGINFO_OFFSET_AUTO}, + {"r11", 4, 11, TCB_REG_OFF(REG_R11), REGINFO_OFFSET_AUTO}, + {"r12", 4, 12, TCB_REG_OFF(REG_R12), REGINFO_OFFSET_AUTO}, + {"sp", 4, 13, TCB_REG_OFF(REG_R13), REGINFO_OFFSET_AUTO}, + {"lr", 4, 14, TCB_REG_OFF(REG_R14), REGINFO_OFFSET_AUTO}, + {"pc", 4, 15, TCB_REG_OFF(REG_R15), REGINFO_OFFSET_AUTO}, + {"xpsr", 4, 25, TCB_REG_OFF(REG_XPSR), REGINFO_OFFSET_AUTO}, }; /**************************************************************************** @@ -116,10 +68,10 @@ const struct tcbinfo_s g_tcbinfo used_data = .stack_off = TCB_STACK_OFF, .stack_size_off = TCB_STACK_SIZE_OFF, .regs_off = TCB_REGS_OFF, - .regs_num = nitems(g_reg_offs), + .regs_num = nitems(g_reginfo), { - .p = g_reg_offs, - }, + .reginfo = g_reginfo, + } }; /**************************************************************************** diff --git a/arch/arm/src/armv8-r/arm_tcbinfo.c b/arch/arm/src/armv8-r/arm_tcbinfo.c index 1580eb05708..888c035e5a6 100644 --- a/arch/arm/src/armv8-r/arm_tcbinfo.c +++ b/arch/arm/src/armv8-r/arm_tcbinfo.c @@ -32,86 +32,46 @@ * Private Data ****************************************************************************/ -static const uint16_t g_reg_offs[] = -{ - TCB_REG_OFF(REG_R0), - TCB_REG_OFF(REG_R1), - TCB_REG_OFF(REG_R2), - TCB_REG_OFF(REG_R3), - TCB_REG_OFF(REG_R4), - TCB_REG_OFF(REG_R5), - TCB_REG_OFF(REG_R6), - TCB_REG_OFF(REG_R7), - TCB_REG_OFF(REG_R8), - TCB_REG_OFF(REG_R9), - TCB_REG_OFF(REG_R10), - TCB_REG_OFF(REG_R11), - TCB_REG_OFF(REG_R12), - TCB_REG_OFF(REG_R13), - TCB_REG_OFF(REG_R14), - TCB_REG_OFF(REG_R15), - TCB_REG_OFF(REG_CPSR), - -#if 0 -# ifdef CONFIG_ARCH_FPU - TCB_REG_OFF(REG_D0), - TCB_REG_OFF(REG_D1), - TCB_REG_OFF(REG_D2), - TCB_REG_OFF(REG_D3), - TCB_REG_OFF(REG_D4), - TCB_REG_OFF(REG_D5), - TCB_REG_OFF(REG_D6), - TCB_REG_OFF(REG_D7), - TCB_REG_OFF(REG_D8), - TCB_REG_OFF(REG_D9), - TCB_REG_OFF(REG_D10), - TCB_REG_OFF(REG_D11), - TCB_REG_OFF(REG_D12), - TCB_REG_OFF(REG_D13), - TCB_REG_OFF(REG_D14), - TCB_REG_OFF(REG_D15), -# endif +/* Name, Size, Regnum, TCB offset, g/G offset */ -# ifdef CONFIG_ARM_DPFPU32 - TCB_REG_OFF(REG_D16), - TCB_REG_OFF(REG_D17), - TCB_REG_OFF(REG_D18), - TCB_REG_OFF(REG_D19), - TCB_REG_OFF(REG_D20), - TCB_REG_OFF(REG_D21), - TCB_REG_OFF(REG_D22), - TCB_REG_OFF(REG_D23), - TCB_REG_OFF(REG_D24), - TCB_REG_OFF(REG_D25), - TCB_REG_OFF(REG_D26), - TCB_REG_OFF(REG_D27), - TCB_REG_OFF(REG_D28), - TCB_REG_OFF(REG_D29), - TCB_REG_OFF(REG_D30), - TCB_REG_OFF(REG_D31), -# endif - -# ifdef CONFIG_ARCH_FPU - TCB_REG_OFF(REG_FPSCR), -# endif -#endif +static const struct reginfo_s g_reginfo[] = +{ + {"r0", 4, 0, TCB_REG_OFF(REG_R0), REGINFO_OFFSET_AUTO}, + {"r1", 4, 1, TCB_REG_OFF(REG_R1), REGINFO_OFFSET_AUTO}, + {"r2", 4, 2, TCB_REG_OFF(REG_R2), REGINFO_OFFSET_AUTO}, + {"r3", 4, 3, TCB_REG_OFF(REG_R3), REGINFO_OFFSET_AUTO}, + {"r4", 4, 4, TCB_REG_OFF(REG_R4), REGINFO_OFFSET_AUTO}, + {"r5", 4, 5, TCB_REG_OFF(REG_R5), REGINFO_OFFSET_AUTO}, + {"r6", 4, 6, TCB_REG_OFF(REG_R6), REGINFO_OFFSET_AUTO}, + {"r7", 4, 7, TCB_REG_OFF(REG_R7), REGINFO_OFFSET_AUTO}, + {"r8", 4, 8, TCB_REG_OFF(REG_R8), REGINFO_OFFSET_AUTO}, + {"r9", 4, 9, TCB_REG_OFF(REG_R9), REGINFO_OFFSET_AUTO}, + {"r10", 4, 10, TCB_REG_OFF(REG_R10), REGINFO_OFFSET_AUTO}, + {"r11", 4, 11, TCB_REG_OFF(REG_R11), REGINFO_OFFSET_AUTO}, + {"r12", 4, 12, TCB_REG_OFF(REG_R12), REGINFO_OFFSET_AUTO}, + {"r13", 4, 13, TCB_REG_OFF(REG_R13), REGINFO_OFFSET_AUTO}, + {"r14", 4, 14, TCB_REG_OFF(REG_R14), REGINFO_OFFSET_AUTO}, + {"r15", 4, 15, TCB_REG_OFF(REG_R15), REGINFO_OFFSET_AUTO}, + {"cpsr", 4, 25, TCB_REG_OFF(REG_CPSR), REGINFO_OFFSET_AUTO}, }; /**************************************************************************** * Public Data ****************************************************************************/ -const struct tcbinfo_s g_tcbinfo = +const struct tcbinfo_s g_tcbinfo used_data = { - .pid_off = TCB_PID_OFF, - .state_off = TCB_STATE_OFF, - .pri_off = TCB_PRI_OFF, - .name_off = TCB_NAME_OFF, - .regs_off = TCB_REGS_OFF, - .regs_num = nitems(g_reg_offs), + .pid_off = TCB_PID_OFF, + .state_off = TCB_STATE_OFF, + .pri_off = TCB_PRI_OFF, + .name_off = TCB_NAME_OFF, + .stack_off = TCB_STACK_OFF, + .stack_size_off = TCB_STACK_SIZE_OFF, + .regs_off = TCB_REGS_OFF, + .regs_num = nitems(g_reginfo), { - .p = g_reg_offs, - }, + .reginfo = g_reginfo, + } }; /**************************************************************************** diff --git a/arch/arm64/src/common/arm64_tcbinfo.c b/arch/arm64/src/common/arm64_tcbinfo.c index cf57a925e1b..331eb5eaa6a 100644 --- a/arch/arm64/src/common/arm64_tcbinfo.c +++ b/arch/arm64/src/common/arm64_tcbinfo.c @@ -32,48 +32,50 @@ * Private Data ****************************************************************************/ -static const uint16_t g_reg_offs[] = +/* Name, Size, Regnum, TCB offset, g/G offset */ + +static const struct reginfo_s g_reginfo[] = { - TCB_REG_OFF(REG_X0), - TCB_REG_OFF(REG_X1), - TCB_REG_OFF(REG_X2), - TCB_REG_OFF(REG_X3), - TCB_REG_OFF(REG_X4), - TCB_REG_OFF(REG_X5), - TCB_REG_OFF(REG_X6), - TCB_REG_OFF(REG_X7), - TCB_REG_OFF(REG_X8), - TCB_REG_OFF(REG_X9), - TCB_REG_OFF(REG_X10), - TCB_REG_OFF(REG_X11), - TCB_REG_OFF(REG_X12), - TCB_REG_OFF(REG_X13), - TCB_REG_OFF(REG_X14), - TCB_REG_OFF(REG_X15), - TCB_REG_OFF(REG_X16), - TCB_REG_OFF(REG_X17), - TCB_REG_OFF(REG_X18), - TCB_REG_OFF(REG_X19), - TCB_REG_OFF(REG_X20), - TCB_REG_OFF(REG_X21), - TCB_REG_OFF(REG_X22), - TCB_REG_OFF(REG_X23), - TCB_REG_OFF(REG_X24), - TCB_REG_OFF(REG_X25), - TCB_REG_OFF(REG_X26), - TCB_REG_OFF(REG_X27), - TCB_REG_OFF(REG_X28), - TCB_REG_OFF(REG_X29), - TCB_REG_OFF(REG_X30), - TCB_REG_OFF(REG_SP_ELX), - TCB_REG_OFF(REG_ELR), + {"x0", 4, 0, TCB_REG_OFF(REG_X0), REGINFO_OFFSET_AUTO}, + {"x1", 4, 1, TCB_REG_OFF(REG_X1), REGINFO_OFFSET_AUTO}, + {"x2", 4, 2, TCB_REG_OFF(REG_X2), REGINFO_OFFSET_AUTO}, + {"x3", 4, 3, TCB_REG_OFF(REG_X3), REGINFO_OFFSET_AUTO}, + {"x4", 4, 4, TCB_REG_OFF(REG_X4), REGINFO_OFFSET_AUTO}, + {"x5", 4, 5, TCB_REG_OFF(REG_X5), REGINFO_OFFSET_AUTO}, + {"x6", 4, 6, TCB_REG_OFF(REG_X6), REGINFO_OFFSET_AUTO}, + {"x7", 4, 7, TCB_REG_OFF(REG_X7), REGINFO_OFFSET_AUTO}, + {"x8", 4, 8, TCB_REG_OFF(REG_X8), REGINFO_OFFSET_AUTO}, + {"x9", 4, 9, TCB_REG_OFF(REG_X9), REGINFO_OFFSET_AUTO}, + {"x10", 4, 10, TCB_REG_OFF(REG_X10), REGINFO_OFFSET_AUTO}, + {"x11", 4, 11, TCB_REG_OFF(REG_X11), REGINFO_OFFSET_AUTO}, + {"x12", 4, 12, TCB_REG_OFF(REG_X12), REGINFO_OFFSET_AUTO}, + {"x13", 4, 13, TCB_REG_OFF(REG_X13), REGINFO_OFFSET_AUTO}, + {"x14", 4, 14, TCB_REG_OFF(REG_X14), REGINFO_OFFSET_AUTO}, + {"x15", 4, 15, TCB_REG_OFF(REG_X15), REGINFO_OFFSET_AUTO}, + {"x16", 4, 16, TCB_REG_OFF(REG_X16), REGINFO_OFFSET_AUTO}, + {"x17", 4, 17, TCB_REG_OFF(REG_X17), REGINFO_OFFSET_AUTO}, + {"x18", 4, 18, TCB_REG_OFF(REG_X18), REGINFO_OFFSET_AUTO}, + {"x19", 4, 19, TCB_REG_OFF(REG_X19), REGINFO_OFFSET_AUTO}, + {"x20", 4, 20, TCB_REG_OFF(REG_X20), REGINFO_OFFSET_AUTO}, + {"x21", 4, 21, TCB_REG_OFF(REG_X21), REGINFO_OFFSET_AUTO}, + {"x22", 4, 22, TCB_REG_OFF(REG_X22), REGINFO_OFFSET_AUTO}, + {"x23", 4, 23, TCB_REG_OFF(REG_X23), REGINFO_OFFSET_AUTO}, + {"x24", 4, 24, TCB_REG_OFF(REG_X24), REGINFO_OFFSET_AUTO}, + {"x25", 4, 25, TCB_REG_OFF(REG_X25), REGINFO_OFFSET_AUTO}, + {"x26", 4, 26, TCB_REG_OFF(REG_X26), REGINFO_OFFSET_AUTO}, + {"x27", 4, 27, TCB_REG_OFF(REG_X27), REGINFO_OFFSET_AUTO}, + {"x28", 4, 28, TCB_REG_OFF(REG_X28), REGINFO_OFFSET_AUTO}, + {"x29", 4, 29, TCB_REG_OFF(REG_X29), REGINFO_OFFSET_AUTO}, + {"x30", 4, 30, TCB_REG_OFF(REG_X30), REGINFO_OFFSET_AUTO}, + {"sp", 4, 31, TCB_REG_OFF(REG_SP_ELX), REGINFO_OFFSET_AUTO}, + {"pc", 4, 32, TCB_REG_OFF(REG_ELR), REGINFO_OFFSET_AUTO}, }; /**************************************************************************** * Public Data ****************************************************************************/ -const struct tcbinfo_s g_tcbinfo = +const struct tcbinfo_s g_tcbinfo used_data = { .pid_off = TCB_PID_OFF, .state_off = TCB_STATE_OFF, @@ -82,10 +84,10 @@ const struct tcbinfo_s g_tcbinfo = .stack_off = TCB_STACK_OFF, .stack_size_off = TCB_STACK_SIZE_OFF, .regs_off = TCB_REGS_OFF, - .regs_num = nitems(g_reg_offs), + .regs_num = nitems(g_reginfo), { - .p = g_reg_offs, - }, + .reginfo = g_reginfo, + } }; /**************************************************************************** diff --git a/arch/risc-v/src/common/riscv_tcbinfo.c b/arch/risc-v/src/common/riscv_tcbinfo.c index 52e0b9c875c..0f2c4b3ef56 100644 --- a/arch/risc-v/src/common/riscv_tcbinfo.c +++ b/arch/risc-v/src/common/riscv_tcbinfo.c @@ -32,81 +32,43 @@ * Private Data ****************************************************************************/ -static const uint16_t g_reg_offs[] = -{ - TCB_REG_OFF(REG_EPC_NDX), /* X0, but it will be ommited by gdb client */ - TCB_REG_OFF(REG_X1_NDX), - TCB_REG_OFF(REG_X2_NDX), - TCB_REG_OFF(REG_X3_NDX), - TCB_REG_OFF(REG_X4_NDX), - TCB_REG_OFF(REG_X5_NDX), - TCB_REG_OFF(REG_X6_NDX), - TCB_REG_OFF(REG_X7_NDX), - TCB_REG_OFF(REG_X8_NDX), - TCB_REG_OFF(REG_X9_NDX), - TCB_REG_OFF(REG_X10_NDX), - TCB_REG_OFF(REG_X11_NDX), - TCB_REG_OFF(REG_X12_NDX), - TCB_REG_OFF(REG_X13_NDX), - TCB_REG_OFF(REG_X14_NDX), - TCB_REG_OFF(REG_X15_NDX), - TCB_REG_OFF(REG_X16_NDX), - TCB_REG_OFF(REG_X17_NDX), - TCB_REG_OFF(REG_X18_NDX), - TCB_REG_OFF(REG_X19_NDX), - TCB_REG_OFF(REG_X20_NDX), - TCB_REG_OFF(REG_X21_NDX), - TCB_REG_OFF(REG_X22_NDX), - TCB_REG_OFF(REG_X23_NDX), - TCB_REG_OFF(REG_X24_NDX), - TCB_REG_OFF(REG_X25_NDX), - TCB_REG_OFF(REG_X26_NDX), - TCB_REG_OFF(REG_X27_NDX), - TCB_REG_OFF(REG_X28_NDX), - TCB_REG_OFF(REG_X29_NDX), - TCB_REG_OFF(REG_X30_NDX), - TCB_REG_OFF(REG_X31_NDX), - TCB_REG_OFF(REG_EPC_NDX), +/* Name, Size, Regnum, TCB offset, g/G offset */ -#if 0 -# ifdef CONFIG_ARCH_FPU - TCB_REG_OFF(REG_F0_NDX), - TCB_REG_OFF(REG_F1_NDX), - TCB_REG_OFF(REG_F2_NDX), - TCB_REG_OFF(REG_F3_NDX), - TCB_REG_OFF(REG_F4_NDX), - TCB_REG_OFF(REG_F5_NDX), - TCB_REG_OFF(REG_F6_NDX), - TCB_REG_OFF(REG_F7_NDX), - TCB_REG_OFF(REG_F8_NDX), - TCB_REG_OFF(REG_F9_NDX), - TCB_REG_OFF(REG_F10_NDX), - TCB_REG_OFF(REG_F11_NDX), - TCB_REG_OFF(REG_F12_NDX), - TCB_REG_OFF(REG_F13_NDX), - TCB_REG_OFF(REG_F14_NDX), - TCB_REG_OFF(REG_F15_NDX), - TCB_REG_OFF(REG_F16_NDX), - TCB_REG_OFF(REG_F17_NDX), - TCB_REG_OFF(REG_F18_NDX), - TCB_REG_OFF(REG_F19_NDX), - TCB_REG_OFF(REG_F20_NDX), - TCB_REG_OFF(REG_F21_NDX), - TCB_REG_OFF(REG_F22_NDX), - TCB_REG_OFF(REG_F23_NDX), - TCB_REG_OFF(REG_F24_NDX), - TCB_REG_OFF(REG_F25_NDX), - TCB_REG_OFF(REG_F26_NDX), - TCB_REG_OFF(REG_F27_NDX), - TCB_REG_OFF(REG_F28_NDX), - TCB_REG_OFF(REG_F29_NDX), - TCB_REG_OFF(REG_F30_NDX), - TCB_REG_OFF(REG_F31_NDX), - UINT16_MAX, /* fflags */ - UINT16_MAX, /* frm */ - TCB_REG_OFF(REG_FCSR_NDX), -# endif -#endif +static const struct reginfo_s g_reginfo[] = +{ + {"zero", 4, 0, TCB_REG_OFF(REG_EPC_NDX), REGINFO_OFFSET_AUTO}, + {"ra", 4, 1, TCB_REG_OFF(REG_X1_NDX), REGINFO_OFFSET_AUTO}, + {"sp", 4, 2, TCB_REG_OFF(REG_X2_NDX), REGINFO_OFFSET_AUTO}, + {"gp", 4, 3, TCB_REG_OFF(REG_X3_NDX), REGINFO_OFFSET_AUTO}, + {"tp", 4, 4, TCB_REG_OFF(REG_X4_NDX), REGINFO_OFFSET_AUTO}, + {"t0", 4, 5, TCB_REG_OFF(REG_X5_NDX), REGINFO_OFFSET_AUTO}, + {"t1", 4, 6, TCB_REG_OFF(REG_X6_NDX), REGINFO_OFFSET_AUTO}, + {"t2", 4, 7, TCB_REG_OFF(REG_X7_NDX), REGINFO_OFFSET_AUTO}, + {"fp", 4, 8, TCB_REG_OFF(REG_X8_NDX), REGINFO_OFFSET_AUTO}, + {"s1", 4, 9, TCB_REG_OFF(REG_X9_NDX), REGINFO_OFFSET_AUTO}, + {"a0", 4, 10, TCB_REG_OFF(REG_X10_NDX), REGINFO_OFFSET_AUTO}, + {"a1", 4, 11, TCB_REG_OFF(REG_X11_NDX), REGINFO_OFFSET_AUTO}, + {"a2", 4, 12, TCB_REG_OFF(REG_X12_NDX), REGINFO_OFFSET_AUTO}, + {"a3", 4, 13, TCB_REG_OFF(REG_X13_NDX), REGINFO_OFFSET_AUTO}, + {"a4", 4, 14, TCB_REG_OFF(REG_X14_NDX), REGINFO_OFFSET_AUTO}, + {"a5", 4, 15, TCB_REG_OFF(REG_X15_NDX), REGINFO_OFFSET_AUTO}, + {"a6", 4, 25, TCB_REG_OFF(REG_X16_NDX), REGINFO_OFFSET_AUTO}, + {"a7", 4, 25, TCB_REG_OFF(REG_X17_NDX), REGINFO_OFFSET_AUTO}, + {"s2", 4, 25, TCB_REG_OFF(REG_X18_NDX), REGINFO_OFFSET_AUTO}, + {"s3", 4, 25, TCB_REG_OFF(REG_X19_NDX), REGINFO_OFFSET_AUTO}, + {"s4", 4, 25, TCB_REG_OFF(REG_X20_NDX), REGINFO_OFFSET_AUTO}, + {"s5", 4, 25, TCB_REG_OFF(REG_X21_NDX), REGINFO_OFFSET_AUTO}, + {"s6", 4, 25, TCB_REG_OFF(REG_X22_NDX), REGINFO_OFFSET_AUTO}, + {"s7", 4, 25, TCB_REG_OFF(REG_X23_NDX), REGINFO_OFFSET_AUTO}, + {"s8", 4, 25, TCB_REG_OFF(REG_X24_NDX), REGINFO_OFFSET_AUTO}, + {"s9", 4, 25, TCB_REG_OFF(REG_X25_NDX), REGINFO_OFFSET_AUTO}, + {"s10", 4, 25, TCB_REG_OFF(REG_X26_NDX), REGINFO_OFFSET_AUTO}, + {"s11", 4, 25, TCB_REG_OFF(REG_X27_NDX), REGINFO_OFFSET_AUTO}, + {"t3", 4, 25, TCB_REG_OFF(REG_X28_NDX), REGINFO_OFFSET_AUTO}, + {"t4", 4, 25, TCB_REG_OFF(REG_X29_NDX), REGINFO_OFFSET_AUTO}, + {"t5", 4, 25, TCB_REG_OFF(REG_X30_NDX), REGINFO_OFFSET_AUTO}, + {"t6", 4, 25, TCB_REG_OFF(REG_X31_NDX), REGINFO_OFFSET_AUTO}, + {"pc", 4, 25, TCB_REG_OFF(REG_EPC_NDX), REGINFO_OFFSET_AUTO}, }; /**************************************************************************** @@ -122,10 +84,10 @@ const struct tcbinfo_s g_tcbinfo used_data = .stack_off = TCB_STACK_OFF, .stack_size_off = TCB_STACK_SIZE_OFF, .regs_off = TCB_REGS_OFF, - .regs_num = nitems(g_reg_offs), + .regs_num = nitems(g_reginfo), { - .p = g_reg_offs, - }, + .reginfo = g_reginfo, + } }; /**************************************************************************** diff --git a/arch/sim/src/sim/sim_tcbinfo.c b/arch/sim/src/sim/sim_tcbinfo.c index 02847da3e26..6470664ec52 100644 --- a/arch/sim/src/sim/sim_tcbinfo.c +++ b/arch/sim/src/sim/sim_tcbinfo.c @@ -33,111 +33,39 @@ ****************************************************************************/ #if defined(CONFIG_HOST_X86_64) && !defined(CONFIG_SIM_M32) -static const uint16_t g_reg_offs[] = +/* Name, Size, Regnum, TCB offset, g/G offset */ + +static const struct reginfo_s g_reginfo[] = { - UINT16_MAX, /* RAX */ - TCB_REG_OFF(JB_RBX), /* RBX */ - UINT16_MAX, /* RCX */ - UINT16_MAX, /* RDX */ - UINT16_MAX, /* RSI */ - UINT16_MAX, /* RDI */ - TCB_REG_OFF(JB_RBP), /* RBP */ - TCB_REG_OFF(JB_RSP), /* RSP */ - UINT16_MAX, /* R8 */ - UINT16_MAX, /* R9 */ - UINT16_MAX, /* R10 */ - UINT16_MAX, /* R11 */ - TCB_REG_OFF(JB_R12), /* R12 */ - TCB_REG_OFF(JB_R13), /* R13 */ - TCB_REG_OFF(JB_R15), /* R14 */ - TCB_REG_OFF(JB_R15), /* R15 */ - TCB_REG_OFF(JB_RIP), /* RIP */ - UINT16_MAX, /* EFLAGS */ - UINT16_MAX, /* CS */ - UINT16_MAX, /* SS */ - UINT16_MAX, /* DS */ - UINT16_MAX, /* ES */ - UINT16_MAX, /* FS */ + {"rbx", 8, 1, TCB_REG_OFF(JB_RBX), REGINFO_OFFSET_INVALID}, + {"rbp", 8, 6, TCB_REG_OFF(JB_RBP), REGINFO_OFFSET_INVALID}, + {"rsp", 8, 7, TCB_REG_OFF(JB_RSP), REGINFO_OFFSET_INVALID}, + {"r12", 8, 12, TCB_REG_OFF(JB_R12), REGINFO_OFFSET_INVALID}, + {"r13", 8, 13, TCB_REG_OFF(JB_R13), REGINFO_OFFSET_INVALID}, + {"r14", 8, 14, TCB_REG_OFF(JB_R14), REGINFO_OFFSET_INVALID}, + {"r15", 8, 15, TCB_REG_OFF(JB_R15), REGINFO_OFFSET_INVALID}, + {"rip", 8, 16, TCB_REG_OFF(JB_RIP), REGINFO_OFFSET_INVALID}, }; #elif defined(CONFIG_HOST_X86) || defined(CONFIG_SIM_M32) -static const uint16_t g_reg_offs[] = +static const struct reginfo_s g_reginfo[] = { - UINT16_MAX, /* RAX */ - UINT16_MAX, /* RCX */ - UINT16_MAX, /* RDX */ - TCB_REG_OFF(JB_EBX), /* RBX */ - TCB_REG_OFF(JB_ESP), /* ESP */ - TCB_REG_OFF(JB_EBP), /* EBP */ - TCB_REG_OFF(JB_ESI), /* ESI */ - TCB_REG_OFF(JB_EDI), /* EDI */ - TCB_REG_OFF(JB_EIP), /* EIP */ - UINT16_MAX, /* EFLAGS */ - UINT16_MAX, /* CS */ - UINT16_MAX, /* SS */ - UINT16_MAX, /* DS */ - UINT16_MAX, /* ES */ - UINT16_MAX, /* FS */ + {"ebx", 4, 1, TCB_REG_OFF(JB_EBX), REGINFO_OFFSET_INVALID}, + {"esp", 4, 2, TCB_REG_OFF(JB_ESP), REGINFO_OFFSET_INVALID}, + {"ebp", 4, 3, TCB_REG_OFF(JB_EBP), REGINFO_OFFSET_INVALID}, + {"esi", 4, 4, TCB_REG_OFF(JB_ESI), REGINFO_OFFSET_INVALID}, + {"edi", 4, 5, TCB_REG_OFF(JB_EDI), REGINFO_OFFSET_INVALID}, + {"eip", 4, 6, TCB_REG_OFF(JB_EIP), REGINFO_OFFSET_INVALID}, }; #elif defined(CONFIG_HOST_ARM64) -static const uint16_t g_reg_offs[] = +static const struct reginfo_s g_reginfo[] = { - UINT16_MAX, - UINT16_MAX, - UINT16_MAX, - UINT16_MAX, - UINT16_MAX, - UINT16_MAX, - UINT16_MAX, - UINT16_MAX, - UINT16_MAX, - UINT16_MAX, - UINT16_MAX, - UINT16_MAX, - UINT16_MAX, - UINT16_MAX, - UINT16_MAX, - UINT16_MAX, - UINT16_MAX, - UINT16_MAX, - UINT16_MAX, - UINT16_MAX, - UINT16_MAX, - UINT16_MAX, - UINT16_MAX, - UINT16_MAX, - UINT16_MAX, - UINT16_MAX, - UINT16_MAX, - UINT16_MAX, - UINT16_MAX, - UINT16_MAX, - UINT16_MAX, - TCB_REG_OFF(JB_SP), - TCB_REG_OFF(JB_PC), - UINT16_MAX, - UINT16_MAX, + {"sp", 8, 31, TCB_REG_OFF(JB_SP), REGINFO_OFFSET_INVALID}, + {"pc", 8, 32, TCB_REG_OFF(JB_PC), REGINFO_OFFSET_INVALID}, }; #elif defined(CONFIG_HOST_ARM) -static const uint16_t g_reg_offs[] = +static const struct reginfo_s g_reginfo[] = { - UINT16_MAX, - UINT16_MAX, - UINT16_MAX, - UINT16_MAX, - UINT16_MAX, - UINT16_MAX, - UINT16_MAX, - UINT16_MAX, - UINT16_MAX, - UINT16_MAX, - UINT16_MAX, - UINT16_MAX, - UINT16_MAX, - UINT16_MAX, - UINT16_MAX, - UINT16_MAX, - UINT16_MAX, - UINT16_MAX, + {"", 4, 0, UINT16_MAX, REGINFO_OFFSET_INVALID}, }; #endif @@ -154,10 +82,10 @@ const struct tcbinfo_s g_tcbinfo used_data = .stack_off = TCB_STACK_OFF, .stack_size_off = TCB_STACK_SIZE_OFF, .regs_off = TCB_REGS_OFF, - .regs_num = nitems(g_reg_offs), + .regs_num = nitems(g_reginfo), { - .p = g_reg_offs, - }, + .reginfo = g_reginfo, + } }; /**************************************************************************** diff --git a/arch/sparc/src/common/sparc_tcbinfo.c b/arch/sparc/src/common/sparc_tcbinfo.c index 97ea9d1cb45..8820850d40f 100644 --- a/arch/sparc/src/common/sparc_tcbinfo.c +++ b/arch/sparc/src/common/sparc_tcbinfo.c @@ -32,40 +32,42 @@ * Private Data ****************************************************************************/ -static const uint16_t g_reg_offs[] = +/* Name, Size, Regnum, TCB offset, g/G offset */ + +static const struct reginfo_s g_reginfo[] = { - UINT16_MAX, /* G0 */ - TCB_REG_OFF(REG_G1), /* G1 */ - TCB_REG_OFF(REG_G2), /* G2 */ - TCB_REG_OFF(REG_G3), /* G3 */ - TCB_REG_OFF(REG_G4), /* G4 */ - TCB_REG_OFF(REG_G5), /* G5 */ - TCB_REG_OFF(REG_G6), /* G6 */ - TCB_REG_OFF(REG_G7), /* G7 */ - TCB_REG_OFF(REG_O0), /* O0 */ - TCB_REG_OFF(REG_O1), /* O1 */ - TCB_REG_OFF(REG_O2), /* O2 */ - TCB_REG_OFF(REG_O3), /* O3 */ - TCB_REG_OFF(REG_O4), /* O4 */ - TCB_REG_OFF(REG_O5), /* O5 */ - TCB_REG_OFF(REG_O6), /* O6 */ - TCB_REG_OFF(REG_O7), /* O7 */ - TCB_REG_OFF(REG_L0), /* L0 */ - TCB_REG_OFF(REG_L1), /* L1 */ - TCB_REG_OFF(REG_L2), /* L2 */ - TCB_REG_OFF(REG_L3), /* L3 */ - TCB_REG_OFF(REG_L4), /* L4 */ - TCB_REG_OFF(REG_L5), /* L5 */ - TCB_REG_OFF(REG_L6), /* L6 */ - TCB_REG_OFF(REG_L7), /* L7 */ - TCB_REG_OFF(REG_I0), /* I0 */ - TCB_REG_OFF(REG_I1), /* I1 */ - TCB_REG_OFF(REG_I2), /* I2 */ - TCB_REG_OFF(REG_I3), /* I3 */ - TCB_REG_OFF(REG_I4), /* I4 */ - TCB_REG_OFF(REG_I5), /* I5 */ - TCB_REG_OFF(REG_I6), /* I6 */ - TCB_REG_OFF(REG_I7), /* I7 */ + {"", 4, 0, REGINFO_OFFSET_INVALID, REGINFO_OFFSET_AUTO}, + {"g1", 4, 1, TCB_REG_OFF(REG_G1), REGINFO_OFFSET_AUTO}, + {"g2", 4, 2, TCB_REG_OFF(REG_G2), REGINFO_OFFSET_AUTO}, + {"g3", 4, 3, TCB_REG_OFF(REG_G3), REGINFO_OFFSET_AUTO}, + {"g4", 4, 4, TCB_REG_OFF(REG_G4), REGINFO_OFFSET_AUTO}, + {"g5", 4, 5, TCB_REG_OFF(REG_G5), REGINFO_OFFSET_AUTO}, + {"g6", 4, 6, TCB_REG_OFF(REG_G6), REGINFO_OFFSET_AUTO}, + {"g7", 4, 7, TCB_REG_OFF(REG_G7), REGINFO_OFFSET_AUTO}, + {"o0", 4, 8, TCB_REG_OFF(REG_O0), REGINFO_OFFSET_AUTO}, + {"o1", 4, 9, TCB_REG_OFF(REG_O1), REGINFO_OFFSET_AUTO}, + {"o2", 4, 10, TCB_REG_OFF(REG_O2), REGINFO_OFFSET_AUTO}, + {"o3", 4, 11, TCB_REG_OFF(REG_O3), REGINFO_OFFSET_AUTO}, + {"o4", 4, 12, TCB_REG_OFF(REG_O4), REGINFO_OFFSET_AUTO}, + {"o5", 4, 13, TCB_REG_OFF(REG_O5), REGINFO_OFFSET_AUTO}, + {"o6", 4, 14, TCB_REG_OFF(REG_O6), REGINFO_OFFSET_AUTO}, + {"o7", 4, 15, TCB_REG_OFF(REG_O7), REGINFO_OFFSET_AUTO}, + {"l0", 4, 16, TCB_REG_OFF(REG_L0), REGINFO_OFFSET_AUTO}, + {"l1", 4, 17, TCB_REG_OFF(REG_L1), REGINFO_OFFSET_AUTO}, + {"l2", 4, 18, TCB_REG_OFF(REG_L2), REGINFO_OFFSET_AUTO}, + {"l3", 4, 19, TCB_REG_OFF(REG_L3), REGINFO_OFFSET_AUTO}, + {"l4", 4, 20, TCB_REG_OFF(REG_L4), REGINFO_OFFSET_AUTO}, + {"l5", 4, 21, TCB_REG_OFF(REG_L5), REGINFO_OFFSET_AUTO}, + {"l6", 4, 22, TCB_REG_OFF(REG_L6), REGINFO_OFFSET_AUTO}, + {"l7", 4, 23, TCB_REG_OFF(REG_L7), REGINFO_OFFSET_AUTO}, + {"i0", 4, 24, TCB_REG_OFF(REG_I0), REGINFO_OFFSET_AUTO}, + {"i1", 4, 25, TCB_REG_OFF(REG_I1), REGINFO_OFFSET_AUTO}, + {"i2", 4, 26, TCB_REG_OFF(REG_I2), REGINFO_OFFSET_AUTO}, + {"i3", 4, 27, TCB_REG_OFF(REG_I3), REGINFO_OFFSET_AUTO}, + {"i4", 4, 28, TCB_REG_OFF(REG_I4), REGINFO_OFFSET_AUTO}, + {"i5", 4, 29, TCB_REG_OFF(REG_I5), REGINFO_OFFSET_AUTO}, + {"i6", 4, 30, TCB_REG_OFF(REG_I6), REGINFO_OFFSET_AUTO}, + {"i7", 4, 31, TCB_REG_OFF(REG_I7), REGINFO_OFFSET_AUTO}, }; /**************************************************************************** @@ -81,10 +83,10 @@ const struct tcbinfo_s g_tcbinfo = .stack_off = TCB_STACK_OFF, .stack_size_off = TCB_STACK_SIZE_OFF, .regs_off = TCB_REGS_OFF, - .regs_num = nitems(g_reg_offs), + .regs_num = nitems(g_reginfo), { - .p = g_reg_offs, - }, + .reginfo = g_reginfo, + } }; /**************************************************************************** diff --git a/arch/tricore/src/common/tricore_tcbinfo.c b/arch/tricore/src/common/tricore_tcbinfo.c index 15d9fd6e767..cc3bc5240e8 100644 --- a/arch/tricore/src/common/tricore_tcbinfo.c +++ b/arch/tricore/src/common/tricore_tcbinfo.c @@ -32,7 +32,9 @@ * Private Data ****************************************************************************/ -static const uint16_t g_reg_offs[1]; +/* Name, Size, Regnum, TCB offset, g/G offset */ + +static const struct reginfo_s g_reginfo[1]; /**************************************************************************** * Public Data @@ -47,9 +49,9 @@ const struct tcbinfo_s g_tcbinfo used_data = .stack_off = TCB_STACK_OFF, .stack_size_off = TCB_STACK_SIZE_OFF, .regs_off = TCB_REGS_OFF, - .regs_num = nitems(g_reg_offs), + .regs_num = nitems(g_reginfo), { - .p = g_reg_offs, + .reginfo = g_reginfo, }, }; diff --git a/arch/x86/src/common/x86_tcbinfo.c b/arch/x86/src/common/x86_tcbinfo.c index 4767a3d3b7b..eed421179d7 100644 --- a/arch/x86/src/common/x86_tcbinfo.c +++ b/arch/x86/src/common/x86_tcbinfo.c @@ -32,23 +32,23 @@ * Private Data ****************************************************************************/ -static const uint16_t g_reg_offs[] = +/* Name, Size, Regnum, TCB offset, g/G offset */ + +static const struct reginfo_s g_reginfo[] = { - TCB_REG_OFF(REG_EAX), /* RAX */ - TCB_REG_OFF(REG_ECX), /* RCX */ - TCB_REG_OFF(REG_EDX), /* RDX */ - TCB_REG_OFF(REG_EBP), /* RBX */ - TCB_REG_OFF(REG_ESP), /* ESP */ - TCB_REG_OFF(REG_EBP), /* EBP */ - TCB_REG_OFF(REG_ESI), /* ESI */ - TCB_REG_OFF(REG_EDI), /* EDI */ - TCB_REG_OFF(REG_EIP), /* EIP */ - TCB_REG_OFF(REG_EFLAGS), /* EFLAGS */ - TCB_REG_OFF(REG_CS), /* CS */ - TCB_REG_OFF(REG_SS), /* SS */ - TCB_REG_OFF(REG_DS), /* DS */ - UINT16_MAX, /* ES */ - UINT16_MAX, /* FS */ + {"eax", 4, 15, TCB_REG_OFF(G_EAX), REGINFO_OFFSET_AUTO}, + {"ecx", 4, 14, TCB_REG_OFF(G_ECX), REGINFO_OFFSET_AUTO}, + {"edx", 4, 13, TCB_REG_OFF(G_EDX), REGINFO_OFFSET_AUTO}, + {"ebp", 4, 12, TCB_REG_OFF(G_EBP), REGINFO_OFFSET_AUTO}, + {"esp", 4, 6, TCB_REG_OFF(G_ESP), REGINFO_OFFSET_AUTO}, + {"ebp", 4, 1, TCB_REG_OFF(G_EBP), REGINFO_OFFSET_AUTO}, + {"esi", 4, 11, TCB_REG_OFF(G_ESI), REGINFO_OFFSET_AUTO}, + {"edi", 4, 10, TCB_REG_OFF(G_EDI), REGINFO_OFFSET_AUTO}, + {"eip", 4, 9, TCB_REG_OFF(G_EIP), REGINFO_OFFSET_AUTO}, + {"eflags", 4, 8, TCB_REG_OFF(G_EFLAGS), REGINFO_OFFSET_AUTO}, + {"cs", 4, 0, TCB_REG_OFF(G_CS), REGINFO_OFFSET_AUTO}, + {"ss", 4, 2, TCB_REG_OFF(G_SS), REGINFO_OFFSET_AUTO}, + {"ds", 4, 3, TCB_REG_OFF(G_DS), REGINFO_OFFSET_AUTO}, }; /**************************************************************************** @@ -64,9 +64,9 @@ const struct tcbinfo_s g_tcbinfo = .stack_off = TCB_STACK_OFF, .stack_size_off = TCB_STACK_SIZE_OFF, .regs_off = TCB_REGS_OFF, - .regs_num = nitems(g_reg_offs), + .regs_num = nitems(g_reginfo), { - .p = g_reg_offs, + .reginfo = g_reginfo, }, }; diff --git a/arch/x86_64/src/common/x86_64_tcbinfo.c b/arch/x86_64/src/common/x86_64_tcbinfo.c index fbb3c5c6732..abbffabc839 100644 --- a/arch/x86_64/src/common/x86_64_tcbinfo.c +++ b/arch/x86_64/src/common/x86_64_tcbinfo.c @@ -32,31 +32,37 @@ * Private Data ****************************************************************************/ -static const uint16_t g_reg_offs[] = +/* Name, Size, Regnum, TCB offset, g/G offset */ + +static const struct reginfo_s g_reginfo[] = { - TCB_REG_OFF(REG_RAX), /* RAX */ - TCB_REG_OFF(REG_RBX), /* RBX */ - TCB_REG_OFF(REG_RCX), /* RCX */ - TCB_REG_OFF(REG_RDX), /* RDX */ - TCB_REG_OFF(REG_RSI), /* RSI */ - TCB_REG_OFF(REG_RDI), /* RDI */ - TCB_REG_OFF(REG_RBP), /* RBP */ - TCB_REG_OFF(REG_RSP), /* RSP */ - TCB_REG_OFF(REG_R8), /* R8 */ - TCB_REG_OFF(REG_R9), /* R9 */ - TCB_REG_OFF(REG_R10), /* R10 */ - TCB_REG_OFF(REG_R11), /* R11 */ - TCB_REG_OFF(REG_R12), /* R12 */ - TCB_REG_OFF(REG_R13), /* R13 */ - TCB_REG_OFF(REG_R14), /* R14 */ - TCB_REG_OFF(REG_R15), /* R15 */ - TCB_REG_OFF(REG_RIP), /* RIP */ - TCB_REG_OFF(REG_RFLAGS), /* EFLAGS */ - TCB_REG_OFF(REG_CS), /* CS */ - TCB_REG_OFF(REG_SS), /* SS */ - TCB_REG_OFF(REG_DS), /* DS */ - TCB_REG_OFF(REG_ES), /* ES */ - TCB_REG_OFF(REG_FS), /* FS */ + {"r15", 8, 15, TCB_REG_OFF(REG_R15), 120}, + {"r14", 8, 14, TCB_REG_OFF(REG_R14), 112}, + {"r13", 8, 13, TCB_REG_OFF(REG_R13), 104}, + {"r12", 8, 12, TCB_REG_OFF(REG_R12), 96}, + {"rbp", 8, 6, TCB_REG_OFF(REG_RBP), 48}, + {"rbx", 8, 1, TCB_REG_OFF(REG_RBX), 8}, + {"r11", 8, 11, TCB_REG_OFF(REG_R11), 88}, + {"r10", 8, 10, TCB_REG_OFF(REG_R10), 80}, + {"r9", 8, 9, TCB_REG_OFF(REG_R9), 72}, + {"r8", 8, 8, TCB_REG_OFF(REG_R8), 64}, + {"rax", 8, 0, TCB_REG_OFF(REG_RAX), 0}, /* g/G 0 */ + {"rcx", 8, 2, TCB_REG_OFF(REG_RCX), 16}, + {"rdx", 8, 3, TCB_REG_OFF(REG_RDX), 24}, + {"rsi", 8, 4, TCB_REG_OFF(REG_RSI), 32}, + {"rdi", 8, 5, TCB_REG_OFF(REG_RDI), 40}, + {"rax", 8, 0, TCB_REG_OFF(REG_RAX), REGINFO_OFFSET_INVALID}, /* orig_ax */ + {"rip", 8, 16, TCB_REG_OFF(REG_RIP), 128}, + {"cs", 4, 18, TCB_REG_OFF(REG_CS), 140}, + {"eflags", 4, 17, TCB_REG_OFF(REG_RFLAGS), 136}, /* GDB expects it to be 4bytes, why? */ + {"rsp", 8, 7, TCB_REG_OFF(REG_RSP), 56}, + {"ss", 4, 19, TCB_REG_OFF(REG_SS), 144}, + {"fs", 4, 22, TCB_REG_OFF(REG_FS), REGINFO_OFFSET_INVALID}, /* fs_base */ + {"gs", 4, 23, TCB_REG_OFF(REG_GS), REGINFO_OFFSET_INVALID}, /* gs_base */ + {"ds", 4, 20, TCB_REG_OFF(REG_DS), 148}, + {"es", 4, 21, TCB_REG_OFF(REG_ES), 152}, + {"fs", 4, 22, TCB_REG_OFF(REG_FS), 156}, + {"gs", 4, 23, TCB_REG_OFF(REG_GS), 160}, }; /**************************************************************************** @@ -72,9 +78,9 @@ const struct tcbinfo_s g_tcbinfo used_data = .stack_off = TCB_STACK_OFF, .stack_size_off = TCB_STACK_SIZE_OFF, .regs_off = TCB_REGS_OFF, - .regs_num = nitems(g_reg_offs), + .regs_num = nitems(g_reginfo), { - .p = g_reg_offs, + .reginfo = g_reginfo, }, }; diff --git a/arch/xtensa/src/common/xtensa_tcbinfo.c b/arch/xtensa/src/common/xtensa_tcbinfo.c index 0102c82fca7..7afc486a1f9 100644 --- a/arch/xtensa/src/common/xtensa_tcbinfo.c +++ b/arch/xtensa/src/common/xtensa_tcbinfo.c @@ -32,26 +32,28 @@ * Private Data ****************************************************************************/ -static const uint16_t g_reg_offs[] = +/* Name, Size, Regnum, TCB offset, g/G offset */ + +static const struct reginfo_s g_reginfo[] = { - TCB_REG_OFF(REG_PC), - TCB_REG_OFF(REG_PS), - TCB_REG_OFF(REG_A0), - TCB_REG_OFF(REG_A1), - TCB_REG_OFF(REG_A2), - TCB_REG_OFF(REG_A3), - TCB_REG_OFF(REG_A4), - TCB_REG_OFF(REG_A5), - TCB_REG_OFF(REG_A6), - TCB_REG_OFF(REG_A7), - TCB_REG_OFF(REG_A8), - TCB_REG_OFF(REG_A9), - TCB_REG_OFF(REG_A10), - TCB_REG_OFF(REG_A11), - TCB_REG_OFF(REG_A12), - TCB_REG_OFF(REG_A13), - TCB_REG_OFF(REG_A14), - TCB_REG_OFF(REG_A15), + {"pc", 4, 0, TCB_REG_OFF(REG_PC), REGINFO_OFFSET_AUTO}, + {"ps", 4, 1, TCB_REG_OFF(REG_PS), REGINFO_OFFSET_AUTO}, + {"a0", 4, 2, TCB_REG_OFF(REG_A0), REGINFO_OFFSET_AUTO}, + {"a1", 4, 3, TCB_REG_OFF(REG_A1), REGINFO_OFFSET_AUTO}, + {"a2", 4, 4, TCB_REG_OFF(REG_A2), REGINFO_OFFSET_AUTO}, + {"a3", 4, 5, TCB_REG_OFF(REG_A3), REGINFO_OFFSET_AUTO}, + {"a4", 4, 6, TCB_REG_OFF(REG_A4), REGINFO_OFFSET_AUTO}, + {"a5", 4, 7, TCB_REG_OFF(REG_A5), REGINFO_OFFSET_AUTO}, + {"a6", 4, 8, TCB_REG_OFF(REG_A6), REGINFO_OFFSET_AUTO}, + {"a7", 4, 9, TCB_REG_OFF(REG_A7), REGINFO_OFFSET_AUTO}, + {"a8", 4, 10, TCB_REG_OFF(REG_A8), REGINFO_OFFSET_AUTO}, + {"a9", 4, 11, TCB_REG_OFF(REG_A9), REGINFO_OFFSET_AUTO}, + {"a10", 4, 12, TCB_REG_OFF(REG_A10), REGINFO_OFFSET_AUTO}, + {"a11", 4, 13, TCB_REG_OFF(REG_A11), REGINFO_OFFSET_AUTO}, + {"a12", 4, 14, TCB_REG_OFF(REG_A12), REGINFO_OFFSET_AUTO}, + {"a13", 4, 15, TCB_REG_OFF(REG_A13), REGINFO_OFFSET_AUTO}, + {"a14", 4, 25, TCB_REG_OFF(REG_A14), REGINFO_OFFSET_AUTO}, + {"a15", 4, 25, TCB_REG_OFF(REG_A15), REGINFO_OFFSET_AUTO}, }; /**************************************************************************** @@ -69,7 +71,7 @@ const struct tcbinfo_s g_tcbinfo used_data = .regs_off = TCB_REGS_OFF, .regs_num = COMMON_CTX_REGS, { - .p = g_reg_offs, + .reginfo = g_reginfo, }, }; diff --git a/include/nuttx/sched.h b/include/nuttx/sched.h index 21cd765819a..e082ab39128 100644 --- a/include/nuttx/sched.h +++ b/include/nuttx/sched.h @@ -246,6 +246,9 @@ #define running_regs() ((void *)(g_running_tasks[this_cpu()]->xcp.regs)) +#define REGINFO_OFFSET_INVALID -2 /* Special value for N/A offset value */ +#define REGINFO_OFFSET_AUTO -1 /* Calculate the offset in GDB g/G packet automatically */ + /**************************************************************************** * Public Type Definitions ****************************************************************************/ @@ -797,6 +800,24 @@ struct pthread_tcb_s }; #endif /* !CONFIG_DISABLE_PTHREAD */ +/* struct reginfo_s *********************************************************/ + +/* The structure describes the register name and size. + * + * For NuttX GDB python plugin, we also use this information to understand + * values in tcb context. + */ + +begin_packed_struct struct reginfo_s +{ + FAR const char *name; /* Register name, must follow GDB, normally in lowercase */ + uint8_t size; /* Register size in bytes */ + uint8_t regnum; /* Remote register number as seen by GDB */ + int16_t toffset; /* Register byte offset in context registers. */ + /* value of REGINFO_OFFSET_INVALID: This register is not provided by NuttX */ + int16_t goffset; /* Register byte offset in g/G packet, default to 0 that means register in order. */ +} end_packed_struct; + /* struct tcbinfo_s *********************************************************/ /* The structure save key filed offset of tcb_s while can be used by @@ -813,20 +834,11 @@ begin_packed_struct struct tcbinfo_s uint16_t stack_size_off; /* Offset of tcb.adj_stack_size */ uint16_t regs_off; /* Offset of tcb.regs */ uint16_t regs_num; /* Num of general regs */ - - /* Offset pointer of xcp.regs, order in GDB org.gnu.gdb.xxx feature. - * Refer to the link of `reg_off` below for more information. - * - * value UINT16_MAX: This register was not provided by NuttX - */ - - begin_packed_struct union { - uint8_t u[8]; - FAR const uint16_t *p; - } - end_packed_struct reg_off; /* Refer to https://sourceware.org/gdb/current/onlinedocs/gdb.html/Standard-Target-Features.html */ + uint8_t u[8]; + FAR const struct reginfo_s *reginfo; /* Register information */ + } u; } end_packed_struct; /* This is the callback type used by nxsched_foreach() */ -- Gitee From 2cfe2c46b631dd45e5ea03e69bdd9b26d0f0f548 Mon Sep 17 00:00:00 2001 From: xuxingliang Date: Mon, 27 Jan 2025 23:57:51 +0800 Subject: [PATCH 211/235] coredump: follow up changes in reginfo VELAPLATFO-53264 Change-Id: I8418de45a70a8464048a2331c84232cfb5c62105 Signed-off-by: xuxingliang --- sched/misc/coredump.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/sched/misc/coredump.c b/sched/misc/coredump.c index e3c7e12e682..353e358dcf7 100644 --- a/sched/misc/coredump.c +++ b/sched/misc/coredump.c @@ -332,10 +332,10 @@ static void elf_emit_tcb_note(FAR struct elf_dumpinfo_s *cinfo, { for (i = 0; i < nitems(status.pr_regs); i++) { - if (g_tcbinfo.reg_off.p[i] != UINT16_MAX) + if (g_tcbinfo.u.reginfo[i].toffset != REGINFO_OFFSET_INVALID) { - status.pr_regs[i] = - *(uintptr_t *)((uint8_t *)regs + g_tcbinfo.reg_off.p[i]); + status.pr_regs[i] = *(uintptr_t *)((uint8_t *)regs + + g_tcbinfo.u.reginfo[i].toffset); } } } -- Gitee From 34502e29b20bd14ad96b4276327109be6effb225 Mon Sep 17 00:00:00 2001 From: xuxingliang Date: Fri, 31 Jan 2025 21:47:12 +0800 Subject: [PATCH 212/235] arch: use same register name in dump and reginfo VELAPLATFO-53264 Change-Id: If2763ed710cf7d5a1fef2e524686184aba758bd0 Signed-off-by: xuxingliang --- arch/arm/src/common/arm_registerdump.c | 15 +++------------ arch/risc-v/src/common/riscv_registerdump.c | 2 +- 2 files changed, 4 insertions(+), 13 deletions(-) diff --git a/arch/arm/src/common/arm_registerdump.c b/arch/arm/src/common/arm_registerdump.c index 2bea5b407e4..c83ae810e6a 100644 --- a/arch/arm/src/common/arm_registerdump.c +++ b/arch/arm/src/common/arm_registerdump.c @@ -64,22 +64,13 @@ void up_dump_register(void *dumpregs) _alert("R0: %08" PRIx32 " R1: %08" PRIx32 " R2: %08" PRIx32 " R3: %08" PRIx32 "\n", regs[REG_R0], regs[REG_R1], regs[REG_R2], regs[REG_R3]); -#ifdef CONFIG_ARM_THUMB - _alert("R4: %08" PRIx32 " R5: %08" PRIx32 - " R6: %08" PRIx32 " FP: %08" PRIx32 "\n", - regs[REG_R4], regs[REG_R5], regs[REG_R6], regs[REG_R7]); - _alert("R8: %08" PRIx32 " SB: %08" PRIx32 - " SL: %08" PRIx32 " R11: %08" PRIx32 "\n", - regs[REG_R8], regs[REG_R9], regs[REG_R10], regs[REG_R11]); -#else _alert("R4: %08" PRIx32 " R5: %08" PRIx32 " R6: %08" PRIx32 " R7: %08" PRIx32 "\n", regs[REG_R4], regs[REG_R5], regs[REG_R6], regs[REG_R7]); - _alert("R8: %08" PRIx32 " SB: %08" PRIx32 - " SL: %08" PRIx32 " FP: %08" PRIx32 "\n", + _alert("R8: %08" PRIx32 " R9: %08" PRIx32 + " R10: %08" PRIx32 " R11: %08" PRIx32 "\n", regs[REG_R8], regs[REG_R9], regs[REG_R10], regs[REG_R11]); -#endif - _alert("IP: %08" PRIx32 " SP: %08" PRIx32 + _alert("R12: %08" PRIx32 " SP: %08" PRIx32 " LR: %08" PRIx32 " PC: %08" PRIx32 "\n", regs[REG_R12], regs[REG_R13], regs[REG_R14], regs[REG_R15]); diff --git a/arch/risc-v/src/common/riscv_registerdump.c b/arch/risc-v/src/common/riscv_registerdump.c index e2913294946..a75b95aa43f 100644 --- a/arch/risc-v/src/common/riscv_registerdump.c +++ b/arch/risc-v/src/common/riscv_registerdump.c @@ -57,7 +57,7 @@ void up_dump_register(void *dumpregs) /* Are user registers available from interrupt processing? */ - _alert("EPC: %" PRIxREG "\n", regs[REG_EPC]); + _alert("PC: %" PRIxREG "\n", regs[REG_EPC]); _alert("A0: %" PRIxREG " A1: %" PRIxREG " A2: %" PRIxREG " A3: %" PRIxREG "\n", regs[REG_A0], regs[REG_A1], regs[REG_A2], regs[REG_A3]); -- Gitee From f89ad4c3d7e075743e5064dfbba0df36edc94aed Mon Sep 17 00:00:00 2001 From: xuxingliang Date: Sat, 4 Jan 2025 03:05:19 +0800 Subject: [PATCH 213/235] arm64: add PC, SP dump for script processing VELAPLATFO-51361 All other arch has the standard register name. Dump the ELR register as PC and SP_ELR register as PC for unified crash dump post processing. Change-Id: I5113dd8e0a4a13deabee972ef73d037052938f66 Signed-off-by: xuxingliang --- arch/arm64/src/common/arm64_registerdump.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/arch/arm64/src/common/arm64_registerdump.c b/arch/arm64/src/common/arm64_registerdump.c index d19dbd704e5..6ecd88938b1 100644 --- a/arch/arm64/src/common/arm64_registerdump.c +++ b/arch/arm64/src/common/arm64_registerdump.c @@ -99,10 +99,14 @@ void up_dump_register(void *dumpregs) _alert("x30: 0x%-16"PRIx64"\n", regs[REG_X30]); _alert("\n"); + + /* Use ELR as PC for script to parse */ + _alert("STATUS Registers:\n"); + _alert("PC: 0x%-16"PRIx64"\n", regs[REG_ELR]); _alert("SPSR: 0x%-16"PRIx64"\n", regs[REG_SPSR]); _alert("ELR: 0x%-16"PRIx64"\n", regs[REG_ELR]); _alert("SP_EL0: 0x%-16"PRIx64"\n", regs[REG_SP_EL0]); - _alert("SP_ELX: 0x%-16"PRIx64"\n", regs[REG_SP_ELX]); + _alert("SP: 0x%-16"PRIx64"\n", regs[REG_SP_ELX]); _alert("EXE_DEPTH: 0x%-16"PRIx64"\n", regs[REG_EXE_DEPTH]); } -- Gitee From efadce550702f71b3bc5621487f48e6355d5aa53 Mon Sep 17 00:00:00 2001 From: xuxingliang Date: Wed, 25 Dec 2024 13:37:38 +0800 Subject: [PATCH 214/235] libc/gdbstub: fix typos VELAPLATFO-50735 Change-Id: I0d4b5457f7b599ae5441644c9cf7e5c208d3e410 Signed-off-by: xuxingliang --- libs/libc/gdbstub/lib_gdbstub.c | 40 ++++++++++++++++----------------- 1 file changed, 20 insertions(+), 20 deletions(-) diff --git a/libs/libc/gdbstub/lib_gdbstub.c b/libs/libc/gdbstub/lib_gdbstub.c index ace13079380..e85dee7d5c1 100644 --- a/libs/libc/gdbstub/lib_gdbstub.c +++ b/libs/libc/gdbstub/lib_gdbstub.c @@ -157,21 +157,21 @@ static ssize_t gdb_put_memory(FAR struct gdb_state_s *state, ****************************************************************************/ /**************************************************************************** - * Name: gdb_expect_seperator + * Name: gdb_expect_separator * * Description: - * Check if the next byte in the packet is a seperator. + * Check if the next byte in the packet is a separator. * * Input Parameters: * state - The pointer to the GDB state structure. - * c - The expected seperator. + * c - The expected separator. * * Returned Value: * 0 on success, -EINVAL on error. * ****************************************************************************/ -static int gdb_expect_seperator(FAR struct gdb_state_s *state, char c) +static int gdb_expect_separator(FAR struct gdb_state_s *state, char c) { if (!state->pkt_next || *state->pkt_next != c) { @@ -213,7 +213,7 @@ static int gdb_expect_integer(FAR struct gdb_state_s *state, } /**************************************************************************** - * Name: gdb_expect_addr_lenth + * Name: gdb_expect_addr_length * * Description: * Parse an address and length argument from the packet. @@ -228,8 +228,8 @@ static int gdb_expect_integer(FAR struct gdb_state_s *state, * ****************************************************************************/ -static int gdb_expect_addr_lenth(FAR struct gdb_state_s *state, - FAR uintptr_t *addr, FAR size_t *length) +static int gdb_expect_addr_length(FAR struct gdb_state_s *state, + FAR uintptr_t *addr, FAR size_t *length) { int ret; @@ -239,7 +239,7 @@ static int gdb_expect_addr_lenth(FAR struct gdb_state_s *state, return ret; } - ret = gdb_expect_seperator(state, ','); + ret = gdb_expect_separator(state, ','); if (ret < 0) { return ret; @@ -1201,7 +1201,7 @@ static int gdb_read_memory(FAR struct gdb_state_s *state) int ret; state->pkt_next++; - ret = gdb_expect_addr_lenth(state, &addr, &length); + ret = gdb_expect_addr_length(state, &addr, &length); if (ret < 0) { return ret; @@ -1244,7 +1244,7 @@ static int gdb_write_memory(FAR struct gdb_state_s *state) int ret; state->pkt_next++; - ret = gdb_expect_addr_lenth(state, &addr, &length); + ret = gdb_expect_addr_length(state, &addr, &length); if (ret < 0) { return ret; @@ -1285,13 +1285,13 @@ static int gdb_write_bin_memory(FAR struct gdb_state_s *state) int ret; state->pkt_next++; - ret = gdb_expect_addr_lenth(state, &addr, &length); + ret = gdb_expect_addr_length(state, &addr, &length); if (ret < 0) { return ret; } - ret = gdb_expect_seperator(state, ':'); + ret = gdb_expect_separator(state, ':'); if (ret < 0) { return ret; @@ -1467,7 +1467,7 @@ static int gdb_query(FAR struct gdb_state_s *state) * * Note : Comand Format: T * id:is the thread id. - * Rsponse Format: OK + * Response Format: OK ****************************************************************************/ static int gdb_is_thread_active(FAR struct gdb_state_s *state) @@ -1510,7 +1510,7 @@ static int gdb_is_thread_active(FAR struct gdb_state_s *state) * * Note : Comand Format: Hg * Hc- - * Rsponse Format: OK + * Response Format: OK ****************************************************************************/ static int gdb_thread_context(FAR struct gdb_state_s *state) @@ -1566,7 +1566,7 @@ static int gdb_thread_context(FAR struct gdb_state_s *state) * 0 if successful. * Negative value on error. * - * Note : Rsponse Format: T AA n1:r1;n2:r2;... + * Note : Response Format: T AA n1:r1;n2:r2;... * The program received signal number AA * n is thread id in current. * r is stop reason. @@ -1708,7 +1708,7 @@ static void gdb_debugpoint_callback(int type, FAR void *addr, * Negative value on error. * * Note : Comand Format: Z/z type,addr,length - * Rsponse Format: OK + * Response Format: OK * Z is set breakpoint. * z is clear breakpoint. * type: 0 is software breakpoint. @@ -1735,7 +1735,7 @@ static int gdb_debugpoint(FAR struct gdb_state_s *state, bool enable) return ret; } - ret = gdb_expect_seperator(state, ','); + ret = gdb_expect_separator(state, ','); if (ret < 0) { return ret; @@ -1747,7 +1747,7 @@ static int gdb_debugpoint(FAR struct gdb_state_s *state, bool enable) return ret; } - ret = gdb_expect_seperator(state, ','); + ret = gdb_expect_separator(state, ','); if (ret < 0) { return ret; @@ -1810,7 +1810,7 @@ static int gdb_debugpoint(FAR struct gdb_state_s *state, bool enable) * Negative value on error. * * Note : Comand Format: s - * Rsponse Format: OK + * Response Format: OK * ****************************************************************************/ @@ -1841,7 +1841,7 @@ static int gdb_step(FAR struct gdb_state_s *state) * Negative value on error. * * Note : Comand Format: c - * Rsponse Format: OK + * Response Format: OK * ****************************************************************************/ -- Gitee From 4a7f2b5a431a0aeeb94f3b39d846218ea745b48c Mon Sep 17 00:00:00 2001 From: xuxingliang Date: Thu, 26 Dec 2024 02:02:17 +0800 Subject: [PATCH 215/235] libc/gdbstub: use rawsyslog for debug log VELAPLATFO-50882 To avoid new line for every character. Change-Id: Id449c09a90a9cf5e1714e252f288c1ec762f301e Signed-off-by: xuxingliang --- libs/libc/gdbstub/lib_gdbstub.c | 35 +++++++++++++++++++++------------ 1 file changed, 22 insertions(+), 13 deletions(-) diff --git a/libs/libc/gdbstub/lib_gdbstub.c b/libs/libc/gdbstub/lib_gdbstub.c index e85dee7d5c1..c9f10b27a1a 100644 --- a/libs/libc/gdbstub/lib_gdbstub.c +++ b/libs/libc/gdbstub/lib_gdbstub.c @@ -29,7 +29,6 @@ #include #include #include -#include #include #include @@ -38,13 +37,16 @@ #include #include #include +#include /**************************************************************************** * Pre-processor Definitions ****************************************************************************/ #ifdef CONFIG_LIB_GDBSTUB_DEBUG -# define GDB_DEBUG(...) syslog(LOG_DEBUG, ##__VA_ARGS__) +# define GDB_DEBUG(stat, ...) \ + lib_sprintf((FAR struct lib_outstream_s *)&state->stream, \ + ##__VA_ARGS__) # define GDB_ASSERT() __assert(__FILE__, __LINE__, 0) #else # define GDB_DEBUG(...) @@ -66,6 +68,9 @@ static const struct memory_region_s g_memory_region[] = struct gdb_state_s { +#ifdef CONFIG_LIB_GDBSTUB_DEBUG + struct lib_syslograwstream_s stream; +#endif gdb_send_func_t send; /* Send buffer to gdb */ gdb_recv_func_t recv; /* Recv buffer from gdb */ FAR void *priv; /* Private data for transport */ @@ -341,20 +346,20 @@ static int gdb_send_packet(FAR struct gdb_state_s *state) #ifdef CONFIG_LIB_GDBSTUB_DEBUG { size_t p; - GDB_DEBUG("-> "); + GDB_DEBUG(state, "-> "); for (p = 0; p < state->pkt_len; p++) { if (isprint(state->pkt_buf[p])) { - GDB_DEBUG("%c", state->pkt_buf[p]); + GDB_DEBUG(state, "%c", state->pkt_buf[p]); } else { - GDB_DEBUG("\\x%02x", state->pkt_buf[p] & 0xff); + GDB_DEBUG(state, "\\x%02x", state->pkt_buf[p] & 0xff); } } - GDB_DEBUG("\n"); + GDB_DEBUG(state, "\n"); } #endif @@ -453,7 +458,7 @@ static int gdb_recv_packet(FAR struct gdb_state_s *state) { if (state->pkt_len >= sizeof(state->pkt_buf)) { - GDB_DEBUG("packet buffer overflow\n"); + GDB_DEBUG(state, "packet buffer overflow\n"); return -EOVERFLOW; } @@ -474,20 +479,20 @@ static int gdb_recv_packet(FAR struct gdb_state_s *state) #ifdef CONFIG_LIB_GDBSTUB_DEBUG { size_t p; - GDB_DEBUG("<- "); + GDB_DEBUG(state, "<- "); for (p = 0; p < state->pkt_len; p++) { if (isprint(state->pkt_buf[p])) { - GDB_DEBUG("%c", state->pkt_buf[p]); + GDB_DEBUG(state, "%c", state->pkt_buf[p]); } else { - GDB_DEBUG("\\x%02x", state->pkt_buf[p] & 0xff); + GDB_DEBUG(state, "\\x%02x", state->pkt_buf[p] & 0xff); } } - GDB_DEBUG("\n"); + GDB_DEBUG(state, "\n"); } #endif @@ -499,7 +504,7 @@ static int gdb_recv_packet(FAR struct gdb_state_s *state) if (csum != gdb_checksum(state->pkt_buf, state->pkt_len)) /* Verify */ { - GDB_DEBUG("received packet with bad checksum\n"); + GDB_DEBUG(state, "received packet with bad checksum\n"); gdb_putchar(state, '-'); /* Send packet nack */ return -EIO; } @@ -562,7 +567,7 @@ static int gdb_recv_ack(FAR struct gdb_state_s *state) case '-': /* Packet negative acknowledged */ return 1; default: /* Bad response! */ - GDB_DEBUG("received bad packet response: 0x%2x\n", response); + GDB_DEBUG(state, "received bad packet response: 0x%2x\n", response); return -EINVAL; } } @@ -1943,6 +1948,10 @@ FAR struct gdb_state_s *gdb_state_init(gdb_send_func_t send, state->priv = priv; state->monitor = monitor; +#ifdef CONFIG_LIB_GDBSTUB_DEBUG + lib_syslograwstream_open(&state->stream); +#endif + return state; } -- Gitee From f8439b51f28dc7901d085c999a43a8804c7263cb Mon Sep 17 00:00:00 2001 From: xuxingliang Date: Wed, 25 Dec 2024 15:00:55 +0800 Subject: [PATCH 216/235] libc/gdbstub: support binary data sent from stub VELAPLATFO-50882 Change-Id: Ieffbd6b8b5c29f9348c85eb6d9e4c6c1498b0fad Signed-off-by: xuxingliang --- drivers/serial/serial_gdbstub.c | 3 +- include/nuttx/gdbstub.h | 2 +- libs/libc/gdbstub/lib_gdbstub.c | 341 +++++++++++++------------------- 3 files changed, 143 insertions(+), 203 deletions(-) diff --git a/drivers/serial/serial_gdbstub.c b/drivers/serial/serial_gdbstub.c index 2c2916bbd30..29d87b137db 100644 --- a/drivers/serial/serial_gdbstub.c +++ b/drivers/serial/serial_gdbstub.c @@ -242,7 +242,8 @@ static ssize_t uart_gdbstub_receive(FAR void *priv, FAR void *buf, * ****************************************************************************/ -static ssize_t uart_gdbstub_send(FAR void *priv, FAR void *buf, size_t len) +static ssize_t uart_gdbstub_send(FAR void *priv, FAR const void *buf, + size_t len) { FAR struct uart_gdbstub_s *uart_gdbstub = priv; FAR uart_dev_t *dev = uart_gdbstub->dev; diff --git a/include/nuttx/gdbstub.h b/include/nuttx/gdbstub.h index 83f40adff5d..4d3c19db3c2 100644 --- a/include/nuttx/gdbstub.h +++ b/include/nuttx/gdbstub.h @@ -47,7 +47,7 @@ ****************************************************************************/ struct gdb_state_s; -typedef CODE ssize_t (*gdb_send_func_t)(FAR void *priv, FAR void *buf, +typedef CODE ssize_t (*gdb_send_func_t)(FAR void *priv, FAR const void *buf, size_t len); typedef CODE ssize_t (*gdb_recv_func_t)(FAR void *priv, FAR void *buf, size_t len); diff --git a/libs/libc/gdbstub/lib_gdbstub.c b/libs/libc/gdbstub/lib_gdbstub.c index c9f10b27a1a..9b87fdd2b83 100644 --- a/libs/libc/gdbstub/lib_gdbstub.c +++ b/libs/libc/gdbstub/lib_gdbstub.c @@ -55,12 +55,8 @@ #define BUFSIZE CONFIG_LIB_GDBSTUB_PKTSIZE -#ifdef CONFIG_BOARD_MEMORY_RANGE -static const struct memory_region_s g_memory_region[] = - { - CONFIG_BOARD_MEMORY_RANGE - }; -#endif +#define REPBIAS 29 +#define REPSIZE (255 - REPBIAS) /**************************************************************************** * Private Types @@ -110,6 +106,13 @@ typedef CODE ssize_t (*gdb_format_func_t)(FAR void *buf, size_t buf_len, * Private Data ****************************************************************************/ +#ifdef CONFIG_BOARD_MEMORY_RANGE +static const struct memory_region_s g_memory_region[] = +{ + CONFIG_BOARD_MEMORY_RANGE +}; +#endif + /**************************************************************************** * Private Functions Prototypes ****************************************************************************/ @@ -117,13 +120,16 @@ typedef CODE ssize_t (*gdb_format_func_t)(FAR void *buf, size_t buf_len, /* System functions, supported by all stubs */ static int gdb_getchar(FAR struct gdb_state_s *state); -static int gdb_putchar(FAR struct gdb_state_s *state, int ch); +static int gdb_putchar(FAR struct gdb_state_s *state, int ch, + FAR char *csum); +static void gdb_escapechar(FAR struct gdb_state_s *state, char c, + FAR char *csum); +static size_t gdb_count_repeat(FAR const char *data, size_t data_len); /* Packet functions */ static int gdb_send_packet(FAR struct gdb_state_s *state); static int gdb_recv_packet(FAR struct gdb_state_s *state); -static int gdb_checksum(FAR const char *buf, size_t len); static int gdb_recv_ack(FAR struct gdb_state_s *state); /* Data format */ @@ -132,9 +138,6 @@ static ssize_t gdb_bin2hex(FAR void *buf, size_t buf_len, FAR const void *data, size_t data_len); static ssize_t gdb_hex2bin(FAR void *buf, size_t buf_len, FAR const void *data, size_t data_len); -static ssize_t gdb_bin2bin(FAR void *buf, size_t buf_len, - FAR const void *data, size_t data_len); -static size_t gdb_encode_rle(FAR void *data, size_t data_len); /* Packet creation helpers */ @@ -272,7 +275,8 @@ static int gdb_expect_addr_length(FAR struct gdb_state_s *state, * ****************************************************************************/ -static int gdb_putchar(FAR struct gdb_state_s *state, int ch) +static int gdb_putchar(FAR struct gdb_state_s *state, int ch, + FAR char *csum) { unsigned char tmp = ch & 0xff; ssize_t ret; @@ -283,9 +287,43 @@ static int gdb_putchar(FAR struct gdb_state_s *state, int ch) return ret; } + if (csum) + { + *csum += (char)tmp; + } + return tmp; } +/**************************************************************************** + * Name: gdb_escapechar + * + * Description: + * Send out a char, do escaping if necessary. + * Do note that for RLE encoded data, the length byte should NOT escape. + * See gdb src of remote.c remote_target::read_frame + * + * Input Parameters: + * state - The pointer to the GDB state structure. + * ch - The character to be sent. + * csum - The checksum. + * + ****************************************************************************/ + +static void gdb_escapechar(FAR struct gdb_state_s *state, char c, + FAR char *csum) +{ + if (c == '#' || c == '$' || c == '}' || c == '*') + { + gdb_putchar(state, '}', csum); + gdb_putchar(state, c ^ 0x20, csum); /* See https://sourceware.org/gdb/current/onlinedocs/gdb.html/Overview.html#Binary-Data */ + } + else + { + gdb_putchar(state, c, csum); + } +} + /**************************************************************************** * Name: gdb_getchar * @@ -333,11 +371,13 @@ static int gdb_getchar(FAR struct gdb_state_s *state) static int gdb_send_packet(FAR struct gdb_state_s *state) { - unsigned char buf[3]; - unsigned char csum; + FAR char *buf = state->pkt_buf; + size_t len = state->pkt_len; + size_t i = 0; + char csum = 0; int ret; - ret = gdb_putchar(state, '$'); /* Send packet start */ + ret = gdb_putchar(state, '$', NULL); /* Send packet start, no checksum */ if (ret < 0) { return ret; @@ -347,15 +387,15 @@ static int gdb_send_packet(FAR struct gdb_state_s *state) { size_t p; GDB_DEBUG(state, "-> "); - for (p = 0; p < state->pkt_len; p++) + for (p = 0; p < len; p++) { - if (isprint(state->pkt_buf[p])) + if (isprint(buf[p])) { - GDB_DEBUG(state, "%c", state->pkt_buf[p]); + GDB_DEBUG(state, "%c", buf[p]); } else { - GDB_DEBUG(state, "\\x%02x", state->pkt_buf[p] & 0xff); + GDB_DEBUG(state, "\\x%02x", buf[p] & 0xff); } } @@ -363,27 +403,54 @@ static int gdb_send_packet(FAR struct gdb_state_s *state) } #endif - state->pkt_len = gdb_encode_rle(state->pkt_buf, state->pkt_len); + while (i < len) + { + const char c = buf[i]; + size_t count = gdb_count_repeat(&buf[i], len - i); - /* Send packet data */ + i += count; + if (count <= 3) + { + while (count-- > 0) + { + gdb_escapechar(state, c, &csum); + } - ret = state->send(state->priv, state->pkt_buf, state->pkt_len); - if (ret < 0) - { - return ret; - } + continue; + } - /* Send the checksum */ + gdb_escapechar(state, c, &csum); /* The data to repeat */ + count--; + + /* Avoid special repeat count. */ + + count += REPBIAS; + if (count == '$') + { + gdb_escapechar(state, c, &csum); + gdb_escapechar(state, c, &csum); + count -= 2; + } + else if (count == '#' || count == 126) + { + gdb_escapechar(state, c, &csum); + count -= 1; + } + + gdb_putchar(state, '*', &csum); + gdb_putchar(state, count, &csum); + } buf[0] = '#'; - csum = gdb_checksum(state->pkt_buf, state->pkt_len); - ret = gdb_bin2hex(buf + 1, sizeof(buf) - 1, &csum, 1); + ret = gdb_bin2hex(buf + 1, 2, &csum, 1); if (ret < 0) { return ret; } - ret = state->send(state->priv, buf, sizeof(buf)); + /* Send the end marker and checksum */ + + ret = state->send(state->priv, buf, 3); if (ret < 0) { return ret; @@ -411,8 +478,10 @@ static int gdb_send_packet(FAR struct gdb_state_s *state) static int gdb_recv_packet(FAR struct gdb_state_s *state) { - unsigned char buf[2]; - unsigned char csum; + bool escaping = false; + char expected; + char buf[2]; + char csum; int ret; /* Wait for packet start */ @@ -442,6 +511,7 @@ static int gdb_recv_packet(FAR struct gdb_state_s *state) /* Read until checksum */ + csum = 0; state->pkt_len = 0; while (1) { @@ -450,22 +520,36 @@ static int gdb_recv_packet(FAR struct gdb_state_s *state) { return ret; } + else if (ret == '}') + { + csum += ret; + escaping = true; + continue; + } + else if (escaping) + { + csum += ret; + ret ^= 0x20; + escaping = false; + } else if (ret == '#') /* End of packet */ { break; } - else /* Check for space */ + else { - if (state->pkt_len >= sizeof(state->pkt_buf)) - { - GDB_DEBUG(state, "packet buffer overflow\n"); - return -EOVERFLOW; - } + csum += ret; + } - /* Store character and update checksum */ + /* Normal or escaped data */ - state->pkt_buf[state->pkt_len++] = (char)ret; + if (state->pkt_len >= sizeof(state->pkt_buf)) + { + GDB_DEBUG(state, "packet buffer overflow\n"); + return -EOVERFLOW; } + + state->pkt_buf[state->pkt_len++] = (char)ret; } } while (state->pkt_len == 0); /* Ignore empty packets */ @@ -496,50 +580,24 @@ static int gdb_recv_packet(FAR struct gdb_state_s *state) } #endif - ret = gdb_hex2bin(&csum, 1, buf, 2); + ret = gdb_hex2bin(&expected, 1, buf, 2); if (ret < 0) { return ret; } - if (csum != gdb_checksum(state->pkt_buf, state->pkt_len)) /* Verify */ + if (csum != expected) /* Verify */ { GDB_DEBUG(state, "received packet with bad checksum\n"); - gdb_putchar(state, '-'); /* Send packet nack */ + gdb_putchar(state, '-', NULL); /* Send packet nack */ return -EIO; } - gdb_putchar(state, '+'); /* Send packet ack */ + gdb_putchar(state, '+', NULL); /* Send packet ack */ state->pkt_next = state->pkt_buf; return 0; } -/**************************************************************************** - * Name: gdb_checksum - * - * Description: - * Calculate 8-bit checksum of a buffer. - * - * Input Parameters: - * buf - The buffer to checksum. - * - * Returned Value: - * 8-bit checksum - * - ****************************************************************************/ - -static int gdb_checksum(FAR const char *buf, size_t len) -{ - unsigned char csum = 0; - - while (len--) - { - csum += *buf++; - } - - return csum; -} - /**************************************************************************** * Name: gdb_recv_ack * @@ -665,65 +723,6 @@ static ssize_t gdb_hex2bin(FAR void *buf, size_t buf_len, return data_len / 2; } -/**************************************************************************** - * Name: gdb_bin2bin - * - * Description: - * Decode data from its bin-value representation to a buffer. - * - * Input Parameters: - * buf - The buffer containing the encoded data. - * buf_len - The length of the buffer. - * data - The buffer to store the decoded data. - * data_len - The length of the data to decode. - * - * Returned Value: - * The number of bytes written to data on success. - * -EOVERFLOW if the output buffer is too small. - * -EINVAL if the input buffer is invalid. - * - ****************************************************************************/ - -static ssize_t gdb_bin2bin(FAR void *buf, size_t buf_len, - FAR const void *data, size_t data_len) -{ - FAR const char *in = data; - FAR char *out = buf; - size_t out_pos = 0; - size_t in_pos; - - for (in_pos = 0; in_pos < data_len; in_pos++) - { - if (out_pos >= buf_len) - { - GDB_ASSERT(); - return -EOVERFLOW; /* Output buffer overflow */ - } - - if (in[in_pos] == '}') /* The next byte is escaped! */ - { - if (in_pos + 1 >= data_len) - { - /* There's an escape character, but no escaped character - * following the escape character. - */ - - GDB_ASSERT(); - return -EINVAL; - } - - in_pos++; - out[out_pos++] = in[in_pos] ^ 0x20; - } - else - { - out[out_pos++] = in[in_pos]; - } - } - - return out_pos; -} - /**************************************************************************** * Name: gdb_count_repeat * @@ -735,7 +734,7 @@ static ssize_t gdb_bin2bin(FAR void *buf, size_t buf_len, * data_len - The length of the data to decode. * * Returned Value: - * The number of bytes repeated. + * The number of bytes repeated, at maximum of REPSIZE. * ****************************************************************************/ @@ -744,7 +743,7 @@ static size_t gdb_count_repeat(FAR const char *data, size_t data_len) char c = data[0]; size_t i = 1; - while (i < data_len && data[i] == c) + while (i < data_len && data[i] == c && i < REPSIZE) { i++; } @@ -752,74 +751,6 @@ static size_t gdb_count_repeat(FAR const char *data, size_t data_len) return i; } -/**************************************************************************** - * Name: gdb_encode_rle - * - * Description: - * Encode data in place using GDB RLE encoding. - * - * Input Parameters: - * data - The buffer containing the encoded data. - * data_len - The length of the data to decode. - * - * Returned Value: - * The number of bytes written to data on success. - * - ****************************************************************************/ - -static size_t gdb_encode_rle(FAR void *data, size_t data_len) -{ - static const int max_count = 127 - 29; - FAR char *buf = data; - size_t widx = 0; - size_t ridx = 0; - - while (ridx < data_len) - { - size_t count = gdb_count_repeat(buf + ridx, data_len - ridx); - char c = buf[ridx]; - - ridx += count; - while (count >= max_count) - { - buf[widx++] = c; - buf[widx++] = '*'; - buf[widx++] = max_count - 1 + 29; - count -= max_count; - } - - if (count <= 3) - { - while (count > 0) - { - buf[widx++] = c; - count--; - } - - continue; - } - - buf[widx++] = c; - count--; - if (count + 29 == '$') - { - buf[widx++] = c; - buf[widx++] = c; - count -= 2; - } - else if (count + 29 == '#') - { - buf[widx++] = c; - count -= 1; - } - - buf[widx++] = '*'; - buf[widx++] = count + 29; - } - - return widx; -} - /**************************************************************************** * Name: gdb_is_valid_region * Description: @@ -919,7 +850,15 @@ static ssize_t gdb_put_memory(FAR struct gdb_state_s *state, if (gdb_is_valid_region(state, addr, len, PF_W)) { - return format((FAR void *)addr, len, buf, buf_len); + if (format) + { + return format((FAR void *)addr, len, buf, buf_len); + } + else + { + ret = MIN(len, buf_len); + memcpy((FAR void *)addr, buf, ret); + } } return ret; @@ -1303,7 +1242,7 @@ static int gdb_write_bin_memory(FAR struct gdb_state_s *state) } ret = gdb_put_memory(state, state->pkt_next, gdb_remaining_len(state), - addr, length, gdb_bin2bin); + addr, length, NULL); if (ret < 0) { return ret; -- Gitee From c1f5af461d94850b5dae9a364282f691c875d973 Mon Sep 17 00:00:00 2001 From: xuxingliang Date: Thu, 26 Dec 2024 02:34:32 +0800 Subject: [PATCH 217/235] libc/gdbstub: add memory binary read support VELAPLATFO-50882 Change-Id: Id7409193875d0d3f573d7c9e7e84aafd8471cc0d Signed-off-by: xuxingliang --- libs/libc/gdbstub/lib_gdbstub.c | 56 ++++++++++++++++++++++++++++++++- 1 file changed, 55 insertions(+), 1 deletion(-) diff --git a/libs/libc/gdbstub/lib_gdbstub.c b/libs/libc/gdbstub/lib_gdbstub.c index 9b87fdd2b83..c5253097ca9 100644 --- a/libs/libc/gdbstub/lib_gdbstub.c +++ b/libs/libc/gdbstub/lib_gdbstub.c @@ -815,7 +815,15 @@ static ssize_t gdb_get_memory(FAR struct gdb_state_s *state, if (gdb_is_valid_region(state, addr, len, PF_R)) { - return format(buf, buf_len, (FAR const void *)addr, len); + if (format) + { + return format(buf, buf_len, (FAR const void *)addr, len); + } + else + { + ret = MIN(len, buf_len); + memcpy(buf, (FAR const void *)addr, ret); + } } return ret; @@ -1164,6 +1172,49 @@ static int gdb_read_memory(FAR struct gdb_state_s *state) return ret; } +/**************************************************************************** + * Name: gdb_read_bin_memory + * + * Description: + * Read Memory (Binary) Command Format: M addr,length + * + * Input Parameters: + * state - The pointer to the GDB state structure. + * + * Returned Value: + * The number of bytes read if successful. + * Negative value on error. + * + * Note : Comand Format: MAAAAAAAAA,LLLLLLLL + * Response Format: bXXXXXXXXYYYYYYYYY... + ****************************************************************************/ + +static int gdb_read_bin_memory(FAR struct gdb_state_s *state) +{ + uintptr_t addr; + size_t length; + int ret; + + state->pkt_next++; + ret = gdb_expect_addr_length(state, &addr, &length); + if (ret < 0) + { + return ret; + } + + state->pkt_buf[0] = 'b'; + ret = gdb_get_memory(state, state->pkt_buf + 1, sizeof(state->pkt_buf) - 1, + addr, length, NULL); + if (ret < 0) + { + return ret; + } + + state->pkt_len = ret + 1; + gdb_send_packet(state); + return ret + 1; +} + /**************************************************************************** * Name: gdb_write_memory * @@ -1998,6 +2049,9 @@ int gdb_process(FAR struct gdb_state_s *state, int stopreason, case 'M': /* Write memory */ ret = gdb_write_memory(state); break; + case 'x': /* Read binary memory */ + ret = gdb_read_bin_memory(state); + break; case 'X': /* Write binary memory */ ret = gdb_write_bin_memory(state); break; -- Gitee From 58f9de3d2559abdcbf9338df7a198d174d271726 Mon Sep 17 00:00:00 2001 From: xuxingliang Date: Thu, 26 Dec 2024 11:56:29 +0800 Subject: [PATCH 218/235] libc/gdbstub: avoid RLE decoding special characters VELAPLATFO-50882 Read/write special data like 0x2a2a2a2a will trigger this issue. The current GDB implementation has this flaw. GDB processes the RLE decoding before espaping the data, make it impossible to repeate special characters. The details can be seen in GDB source code remote.c remote_target::read_frame function. Change-Id: I35c6bdbb4770fdaff54fc0f2f53e7dd562666270 Signed-off-by: xuxingliang --- libs/libc/gdbstub/lib_gdbstub.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/libs/libc/gdbstub/lib_gdbstub.c b/libs/libc/gdbstub/lib_gdbstub.c index c5253097ca9..3e3ebfb44dc 100644 --- a/libs/libc/gdbstub/lib_gdbstub.c +++ b/libs/libc/gdbstub/lib_gdbstub.c @@ -409,6 +409,19 @@ static int gdb_send_packet(FAR struct gdb_state_s *state) size_t count = gdb_count_repeat(&buf[i], len - i); i += count; + + /* GDB cannot process repeated special characters. */ + + if (c == '*' || c == '}' || c == '#' || c == '$') + { + while (count--) + { + gdb_escapechar(state, c, &csum); + } + + continue; + } + if (count <= 3) { while (count-- > 0) -- Gitee From f130b3a1b998658e7a2ef96b3306ee904845df8a Mon Sep 17 00:00:00 2001 From: xuxingliang Date: Mon, 27 Jan 2025 14:39:50 +0800 Subject: [PATCH 219/235] gdbstub: support P packet to write single register VELAPLATFO-53048 Change-Id: I787ddd6b98448ede633139a222450f7b49e51067 Signed-off-by: xuxingliang --- libs/libc/gdbstub/lib_gdbstub.c | 58 +++++++++++++++++++++++++++++++++ 1 file changed, 58 insertions(+) diff --git a/libs/libc/gdbstub/lib_gdbstub.c b/libs/libc/gdbstub/lib_gdbstub.c index 3e3ebfb44dc..0791eff0fa3 100644 --- a/libs/libc/gdbstub/lib_gdbstub.c +++ b/libs/libc/gdbstub/lib_gdbstub.c @@ -1142,6 +1142,61 @@ static int gdb_read_register(FAR struct gdb_state_s *state) return 0; } +/**************************************************************************** + * Name: gdb_write_register + * + * Description: + * Write a Register Command Format: P n. + * Note that this won't work for all architectures because the GDB remote + * register number is not always the same as the NuttX register number. + * + * Input Parameters: + * state - The pointer to the GDB state structure. + * + * Returned Value: + * Zero on success. + * Negative value on error. + * + * Note: Comand Format: Pn. + * Response Format: OK or negative value for error number. + ****************************************************************************/ + +static int gdb_write_register(FAR struct gdb_state_s *state) +{ + uintptr_t addr; + int ret; + + state->pkt_next++; + + ret = gdb_expect_integer(state, &addr); + if (ret < 0) + { + return ret; + } + + ret = gdb_expect_separator(state, '='); + if (ret < 0) + { + return ret; + } + + if (addr > state->size / sizeof(uintptr_t) - 1) + { + return -EINVAL; + } + + ret = gdb_hex2bin(&state->registers[addr], sizeof(uintptr_t), + state->pkt_next, gdb_remaining_len(state)); + + if (ret < 0) + { + return ret; + } + + gdb_send_ok_packet(state); + return 0; +} + /**************************************************************************** * Name: gdb_read_memory * @@ -2056,6 +2111,9 @@ int gdb_process(FAR struct gdb_state_s *state, int stopreason, case 'p': /* Read one register */ ret = gdb_read_register(state); break; + case 'P': /* Write one register */ + ret = gdb_write_register(state); + break; case 'm': /* Read memory */ ret = gdb_read_memory(state); break; -- Gitee From 6094e96d67810d48acad54b82d9db4e322296aa9 Mon Sep 17 00:00:00 2001 From: xuxingliang Date: Mon, 27 Jan 2025 14:33:26 +0800 Subject: [PATCH 220/235] gdbstub: fix register write VELAPLATFO-53048 The register write operation is not working because: 1. wrong parameter in buffer size. 2. register value get flushed on the next read operation. Since we cannot change the thread's register freely. We maintain a copy of register values in gdbstub, and update the cache when switch to different thread. Write register will only affect the cached register Change-Id: I5eb491035b81f29106ea28a6c6a55db5b20f4f9b Signed-off-by: xuxingliang --- libs/libc/gdbstub/lib_gdbstub.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/libs/libc/gdbstub/lib_gdbstub.c b/libs/libc/gdbstub/lib_gdbstub.c index 0791eff0fa3..53952c2c10b 100644 --- a/libs/libc/gdbstub/lib_gdbstub.c +++ b/libs/libc/gdbstub/lib_gdbstub.c @@ -984,7 +984,7 @@ static int gdb_send_error_packet(FAR struct gdb_state_s *state, ****************************************************************************/ /**************************************************************************** - * Name: gdb_get_registers + * Name: gdb_update_regcache * * Description: * Get the registers of the specified task. @@ -993,7 +993,7 @@ static int gdb_send_error_packet(FAR struct gdb_state_s *state, * state - The pointer to the GDB state structure. ****************************************************************************/ -static void gdb_get_registers(FAR struct gdb_state_s *state) +static void gdb_update_regcache(FAR struct gdb_state_s *state) { FAR struct tcb_s *tcb = nxsched_get_tcb(state->pid); FAR uint8_t *reg; @@ -1048,7 +1048,6 @@ static int gdb_read_registers(FAR struct gdb_state_s *state) { int ret; - gdb_get_registers(state); ret = gdb_bin2hex(state->pkt_buf, sizeof(state->pkt_buf), state->registers, state->size); if (ret < 0) @@ -1084,7 +1083,7 @@ static int gdb_write_registers(FAR struct gdb_state_s *state) { int ret; - ret = gdb_hex2bin(state->registers, sizeof(state->registers), + ret = gdb_hex2bin(state->registers, state->size, state->pkt_buf + 1, state->pkt_len - 1); if (ret < 0) { @@ -1096,10 +1095,10 @@ static int gdb_write_registers(FAR struct gdb_state_s *state) } /**************************************************************************** - * Name: gdb_write_register + * Name: gdb_read_register * * Description: - * Write a Register Command Format: P n. + * Read a Register Command Format: p n. * * Input Parameters: * state - The pointer to the GDB state structure. @@ -1124,7 +1123,6 @@ static int gdb_read_register(FAR struct gdb_state_s *state) return ret; } - gdb_get_registers(state); if (addr >= state->size) { return 0; @@ -1612,6 +1610,8 @@ static int gdb_thread_context(FAR struct gdb_state_s *state) state->pid = pid - 1; } + gdb_update_regcache(state); + gdb_send_ok_packet(state); return 0; } -- Gitee From e1cd5b2b3e2b409564678679754874b863beb329 Mon Sep 17 00:00:00 2001 From: xuxingliang Date: Fri, 7 Feb 2025 20:52:52 +0800 Subject: [PATCH 221/235] gdbstub: should update register cache whenever CPU stops VELAPLATFO-53264 Change-Id: I939fa9c48dc29c895863a21250cbba870d7021d8 Signed-off-by: xuxingliang --- libs/libc/gdbstub/lib_gdbstub.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/libs/libc/gdbstub/lib_gdbstub.c b/libs/libc/gdbstub/lib_gdbstub.c index 53952c2c10b..66fd5087eb6 100644 --- a/libs/libc/gdbstub/lib_gdbstub.c +++ b/libs/libc/gdbstub/lib_gdbstub.c @@ -2090,6 +2090,8 @@ int gdb_process(FAR struct gdb_state_s *state, int stopreason, if (stopreason != GDB_STOPREASON_NONE) { + state->pid = _SCHED_GETTID(); + gdb_update_regcache(state); gdb_send_stop(state, stopreason, stopaddr); } -- Gitee From c5dc685d4dc626623a06ca822e3f1c492f561c31 Mon Sep 17 00:00:00 2001 From: p-szafonimateusz Date: Tue, 17 Dec 2024 13:23:42 +0100 Subject: [PATCH 222/235] libs/libc/gdbstub/lib_gdbstub.c: fix format for trap response gdb crash after a few step breakpoints because trap is not correctly reported Change-Id: I1dc185c95db254ebf0bbf1ee7622237d136b9f32 Signed-off-by: p-szafonimateusz --- libs/libc/gdbstub/lib_gdbstub.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libs/libc/gdbstub/lib_gdbstub.c b/libs/libc/gdbstub/lib_gdbstub.c index 66fd5087eb6..2f4fcc30c93 100644 --- a/libs/libc/gdbstub/lib_gdbstub.c +++ b/libs/libc/gdbstub/lib_gdbstub.c @@ -1672,7 +1672,7 @@ retry: case GDB_STOPREASON_CTRLC: default: - ret = sprintf(state->pkt_buf, "T05thread:%d;", state->pid + 1); + ret = sprintf(state->pkt_buf, "T05thread:%x;", state->pid + 1); } if (ret < 0) -- Gitee From caf3a10c160b142013b26ae6d5303fa06d2a485c Mon Sep 17 00:00:00 2001 From: p-szafonimateusz Date: Mon, 16 Dec 2024 11:35:24 +0100 Subject: [PATCH 223/235] libs/libc/gdbstub/lib_gdbstub.c: fix warning Change-Id: I77d43fb7d8a32bfb8fb774aa56f3782cd908b099 Signed-off-by: p-szafonimateusz --- libs/libc/gdbstub/lib_gdbstub.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libs/libc/gdbstub/lib_gdbstub.c b/libs/libc/gdbstub/lib_gdbstub.c index 2f4fcc30c93..6e4ee151235 100644 --- a/libs/libc/gdbstub/lib_gdbstub.c +++ b/libs/libc/gdbstub/lib_gdbstub.c @@ -1437,11 +1437,11 @@ static int gdb_query(FAR struct gdb_state_s *state) { #ifdef CONFIG_ARCH_HAVE_DEBUG state->pkt_len = sprintf(state->pkt_buf, - "hwbreak+;PacketSize=%x", + "hwbreak+;PacketSize=%zx", sizeof(state->pkt_buf)); #else state->pkt_len = sprintf(state->pkt_buf, - "PacketSize=%x", + "PacketSize=%zx", sizeof(state->pkt_buf)); #endif gdb_send_packet(state); -- Gitee From c418fb7afd250c106fb0e097de09f006bd73bb4a Mon Sep 17 00:00:00 2001 From: xuxingliang Date: Fri, 17 Jan 2025 17:54:13 +0800 Subject: [PATCH 224/235] gdbstub: replace process ID 0 to a valid value VELAPLATFO-52290 GDB uses id 0 to indicate any thread in RSP protocol. Previously use NuttX pid + 1 to avoid using ID 0. Now we replace 0 with a non-zero value. In this way, the thread ID shows in GDB will match directly with NuttX, makes it better for debugging. As for 0 which is the IDLE thread, we can easily idendify it too. Change-Id: I5eab96e52d043362136837af8fd02ef2e372a33e Signed-off-by: xuxingliang --- libs/libc/gdbstub/lib_gdbstub.c | 56 +++++++++++++++++++++++---------- 1 file changed, 39 insertions(+), 17 deletions(-) diff --git a/libs/libc/gdbstub/lib_gdbstub.c b/libs/libc/gdbstub/lib_gdbstub.c index 6e4ee151235..4b198b32558 100644 --- a/libs/libc/gdbstub/lib_gdbstub.c +++ b/libs/libc/gdbstub/lib_gdbstub.c @@ -58,6 +58,14 @@ #define REPBIAS 29 #define REPSIZE (255 - REPBIAS) +/* Architecture can overwrite the default XCPTCONTEXT alignment */ + +#ifndef XCPTCONTEXT_ALIGN +# define XCPTCONTEXT_ALIGN 16 +#endif + +#define PID0_REPLACE INT32_MAX + /**************************************************************************** * Private Types ****************************************************************************/ @@ -75,7 +83,7 @@ struct gdb_state_s */ int last_stopreason; /* Last stop reason */ FAR void *last_stopaddr; /* Last stop address */ - pid_t pid; /* Gdb current thread */ + pid_t pid; /* Current NuttX thread pid */ FAR char *pkt_next; /* Pointer to next byte in packet */ char pkt_buf[BUFSIZE]; /* Packet buffer */ size_t pkt_len; /* Packet send and receive length */ @@ -1382,12 +1390,9 @@ static int gdb_write_bin_memory(FAR struct gdb_state_s *state) static void gdb_get_thread(FAR struct tcb_s *tcb, FAR void *arg) { + int pid = tcb->pid == 0 ? PID0_REPLACE : tcb->pid; FAR struct gdb_state_s *state = arg; - int pid = tcb->pid; - - /* Gdb pid start from 1, so add it */ - - state->pkt_len += sprintf(&state->pkt_buf[state->pkt_len], "%x,", pid + 1); + state->pkt_len += sprintf(&state->pkt_buf[state->pkt_len], "%x,", pid); } /**************************************************************************** @@ -1462,7 +1467,12 @@ static int gdb_query(FAR struct gdb_state_s *state) return ret; } - tcb = nxsched_get_tcb(pid - 1); + if (pid == PID0_REPLACE) + { + pid = 0; + } + + tcb = nxsched_get_tcb(pid); if (tcb == NULL) { return -EINVAL; @@ -1544,13 +1554,18 @@ static int gdb_is_thread_active(FAR struct gdb_state_s *state) return ret; } - tcb = nxsched_get_tcb(pid - 1); + if (pid == PID0_REPLACE) + { + pid = 0; + } + + tcb = nxsched_get_tcb(pid); if (tcb == NULL) { return -EINVAL; } - state->pid = pid - 1; + state->pid = pid; gdb_send_ok_packet(state); return ret; } @@ -1601,13 +1616,14 @@ static int gdb_thread_context(FAR struct gdb_state_s *state) if (pid != 0) { - tcb = nxsched_get_tcb(pid - 1); + pid = pid == PID0_REPLACE ? 0 : pid; + tcb = nxsched_get_tcb(pid); if (tcb == NULL) { return -EINVAL; } - state->pid = pid - 1; + state->pid = pid; } gdb_update_regcache(state); @@ -1640,26 +1656,32 @@ static int gdb_send_stop(FAR struct gdb_state_s *state, int stopreason, FAR void *stopaddr) { int ret; + int pid; + + state->pid = pid = _SCHED_GETTID(); + if (pid == 0) + { + pid = PID0_REPLACE; + } - state->pid = _SCHED_GETTID(); retry: switch (stopreason) { case GDB_STOPREASON_WATCHPOINT_RO: ret = sprintf(state->pkt_buf, "T05thread:%x;rwatch:%" PRIxPTR ";", - state->pid + 1, (uintptr_t)stopaddr); + pid, (uintptr_t)stopaddr); break; case GDB_STOPREASON_WATCHPOINT_WO: ret = sprintf(state->pkt_buf, "T05thread:%x;awatch:%" PRIxPTR ";", - state->pid + 1, (uintptr_t)stopaddr); + pid, (uintptr_t)stopaddr); break; case GDB_STOPREASON_WATCHPOINT_RW: ret = sprintf(state->pkt_buf, "T05thread:%x;watch:%" PRIxPTR ";", - state->pid + 1, (uintptr_t)stopaddr); + pid, (uintptr_t)stopaddr); break; case GDB_STOPREASON_BREAKPOINT: ret = sprintf(state->pkt_buf, "T05thread:%x;hwbreak:;", - state->pid + 1); + pid); break; case GDB_STOPREASON_STEPPOINT: if (state->last_stopreason == GDB_STOPREASON_WATCHPOINT_RW || @@ -1672,7 +1694,7 @@ retry: case GDB_STOPREASON_CTRLC: default: - ret = sprintf(state->pkt_buf, "T05thread:%x;", state->pid + 1); + ret = sprintf(state->pkt_buf, "T05thread:%x;", pid); } if (ret < 0) -- Gitee From ec2d1bd0922426aec8b0a6e5c49e1c4f70d9fc3a Mon Sep 17 00:00:00 2001 From: xuxingliang Date: Fri, 17 Jan 2025 18:00:44 +0800 Subject: [PATCH 225/235] gdbstub: fix Hg/Hc packet parsing VELAPLATFO-52290 The Hg/Hc packet could send negative thread ID, Hc is the packet prefix, not the `Hc-`. Change-Id: Iaedf5f5aef8ad9099e4b5c2afcc6150fd0b68a95 Signed-off-by: xuxingliang --- libs/libc/gdbstub/lib_gdbstub.c | 40 ++++++++++++++++++--------------- 1 file changed, 22 insertions(+), 18 deletions(-) diff --git a/libs/libc/gdbstub/lib_gdbstub.c b/libs/libc/gdbstub/lib_gdbstub.c index 4b198b32558..f5b7848aa72 100644 --- a/libs/libc/gdbstub/lib_gdbstub.c +++ b/libs/libc/gdbstub/lib_gdbstub.c @@ -1576,6 +1576,8 @@ static int gdb_is_thread_active(FAR struct gdb_state_s *state) * Description: * The thread context packet is used by GDB to request information from * the stub. + * Set thread for subsequent operations (m, M, g, G, etc) + * Thread ID of -1 means all all thread, 0 means any thread. * * Input Parameters: * state - The pointer to the GDB state structure. @@ -1585,7 +1587,7 @@ static int gdb_is_thread_active(FAR struct gdb_state_s *state) * Negative value on error. * * Note : Comand Format: Hg - * Hc- + * Hc * Response Format: OK ****************************************************************************/ @@ -1594,37 +1596,39 @@ static int gdb_thread_context(FAR struct gdb_state_s *state) FAR struct tcb_s *tcb; uintptr_t pid; int ret; + char c = state->pkt_buf[1]; - if (state->pkt_buf[1] == 'g') - { - state->pkt_next += 2; - } - else if (state->pkt_buf[1] == 'c') - { - state->pkt_next += 3; - } - else + if (c != 'g' && c != 'c') { return -EINVAL; } + state->pkt_next += 2; /* Skip Hg/Hc */ + ret = gdb_expect_integer(state, &pid); if (ret < 0) { return ret; } - if (pid != 0) + if (pid == 0 || pid == -1) { - pid = pid == PID0_REPLACE ? 0 : pid; - tcb = nxsched_get_tcb(pid); - if (tcb == NULL) - { - return -EINVAL; - } + /* ‘-1’ to indicate all threads, or ‘0’ to pick any thread. */ - state->pid = pid; + pid = state->pid; /* Keep unchanged */ } + else if (pid == PID0_REPLACE) + { + pid = 0; + } + + tcb = nxsched_get_tcb(pid); + if (tcb == NULL) + { + return -EINVAL; + } + + state->pid = pid; gdb_update_regcache(state); -- Gitee From c8d36bd8d92a1ec1fc62f955e4d0bac10bffa6ab Mon Sep 17 00:00:00 2001 From: p-szafonimateusz Date: Thu, 9 Jan 2025 15:37:41 +0100 Subject: [PATCH 226/235] libc/lib_gdbstub.c: running_regs must be aligned Change-Id: I4dd634f737b53904c6c1e7420e8943ca56e18bd8 Signed-off-by: p-szafonimateusz --- libs/libc/gdbstub/lib_gdbstub.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/libs/libc/gdbstub/lib_gdbstub.c b/libs/libc/gdbstub/lib_gdbstub.c index f5b7848aa72..a69a70fdfb6 100644 --- a/libs/libc/gdbstub/lib_gdbstub.c +++ b/libs/libc/gdbstub/lib_gdbstub.c @@ -87,7 +87,7 @@ struct gdb_state_s FAR char *pkt_next; /* Pointer to next byte in packet */ char pkt_buf[BUFSIZE]; /* Packet buffer */ size_t pkt_len; /* Packet send and receive length */ - uint8_t running_regs[XCPTCONTEXT_SIZE]; /* Registers of running thread */ + FAR uint8_t *running_regs; /* Registers of running thread */ size_t size; /* Size of registers */ uintptr_t registers[0]; /* Registers of other threads */ }; @@ -2031,6 +2031,7 @@ FAR struct gdb_state_s *gdb_state_init(gdb_send_func_t send, state->recv = recv; state->priv = priv; state->monitor = monitor; + state->running_regs = lib_memalign(XCPTCONTEXT_ALIGN, XCPTCONTEXT_SIZE); #ifdef CONFIG_LIB_GDBSTUB_DEBUG lib_syslograwstream_open(&state->stream); @@ -2054,6 +2055,7 @@ void gdb_state_uninit(FAR struct gdb_state_s *state) { if (state != NULL) { + lib_free(state->running_regs); lib_free(state); } } -- Gitee From a1e398e7e88f0379fc175e7f0f21faba6c1924ed Mon Sep 17 00:00:00 2001 From: xuxingliang Date: Mon, 27 Jan 2025 16:52:04 +0800 Subject: [PATCH 227/235] gdbstub: use register info to make the g/G packet work VELAPLATFO-53264 This patch addresses the issue where the remote register numbers defined in GDB may contain gaps. It resolves this by leveraging the reginfo structure, which provides a mapping between NuttX registers and GDB remote registers. While using XML to describe the NuttX register layout would be ideal, this approach is necessary as some architectures do not support XML descriptors. Additionally, the reginfo mechanism ensures correctness for the i386:x86-64 architecture, where the register layout in coredumps is inconsistent with GDB's default remote register layout. This improvement enhances compatibility and reliability when working with GDB. Change-Id: Ib1dc47cc12c89cfcc7f41a603334a9bb7ccaacba Signed-off-by: xuxingliang --- libs/libc/gdbstub/lib_gdbstub.c | 129 ++++++++++++++++++++++---------- 1 file changed, 91 insertions(+), 38 deletions(-) diff --git a/libs/libc/gdbstub/lib_gdbstub.c b/libs/libc/gdbstub/lib_gdbstub.c index a69a70fdfb6..90b9f4285e8 100644 --- a/libs/libc/gdbstub/lib_gdbstub.c +++ b/libs/libc/gdbstub/lib_gdbstub.c @@ -88,8 +88,7 @@ struct gdb_state_s char pkt_buf[BUFSIZE]; /* Packet buffer */ size_t pkt_len; /* Packet send and receive length */ FAR uint8_t *running_regs; /* Registers of running thread */ - size_t size; /* Size of registers */ - uintptr_t registers[0]; /* Registers of other threads */ + FAR void *xcpregs; /* Pointer to the registers in context. */ }; struct gdb_debugpoint_s @@ -1005,7 +1004,6 @@ static void gdb_update_regcache(FAR struct gdb_state_s *state) { FAR struct tcb_s *tcb = nxsched_get_tcb(state->pid); FAR uint8_t *reg; - int i; reg = (FAR uint8_t *)tcb->xcp.regs; if (state->pid == _SCHED_GETTID()) @@ -1021,18 +1019,22 @@ static void gdb_update_regcache(FAR struct gdb_state_s *state) } } - for (i = 0; i < state->size / sizeof(uintptr_t); i++) + state->xcpregs = reg; +} + +static FAR const struct reginfo_s * gdb_find_reginfo(int regnum) +{ + size_t i; + for (i = 0; i < g_tcbinfo.regs_num; i++) { - if (g_tcbinfo.reg_off.p[i] == UINT16_MAX) + if (g_tcbinfo.u.reginfo[i].regnum == regnum && + g_tcbinfo.u.reginfo[i].goffset != REGINFO_OFFSET_INVALID) { - state->registers[i] = 0; - } - else - { - state->registers[i] = - *(FAR uintptr_t *)(reg + g_tcbinfo.reg_off.p[i]); + return &g_tcbinfo.u.reginfo[i]; } } + + return NULL; } /**************************************************************************** @@ -1054,18 +1056,41 @@ static void gdb_update_regcache(FAR struct gdb_state_s *state) static int gdb_read_registers(FAR struct gdb_state_s *state) { + FAR const char *xcpregs = state->xcpregs; + ssize_t offset = 0; /* Offset in g/G packet */ + size_t i; int ret; - ret = gdb_bin2hex(state->pkt_buf, sizeof(state->pkt_buf), - state->registers, state->size); - if (ret < 0) + memset(state->pkt_buf, 'x', BUFSIZE); + + for (i = 0; i < g_tcbinfo.regs_num; i++) { - return ret; + FAR const struct reginfo_s *reg = &g_tcbinfo.u.reginfo[i]; + uintptr_t value = 0; + + if (reg->goffset == REGINFO_OFFSET_INVALID) + { + continue; + } + else if (reg->goffset != REGINFO_OFFSET_AUTO) + { + offset = reg->goffset; + } + + memcpy(&value, xcpregs + reg->toffset, reg->size); + ret = gdb_bin2hex(&state->pkt_buf[offset * 2], + BUFSIZE - offset, + &value, reg->size); + if (ret < 0) + { + return ret; + } + + offset += reg->size; } - state->pkt_len = ret; + state->pkt_len = offset * 2; gdb_send_packet(state); - return 0; } @@ -1089,13 +1114,28 @@ static int gdb_read_registers(FAR struct gdb_state_s *state) static int gdb_write_registers(FAR struct gdb_state_s *state) { + FAR char *xcpregs = state->xcpregs; + ssize_t offset = 0; /* Offset in g/G packet */ + size_t i; int ret; - ret = gdb_hex2bin(state->registers, state->size, - state->pkt_buf + 1, state->pkt_len - 1); - if (ret < 0) + for (i = 0; i < g_tcbinfo.regs_num; i++) { - return ret; + FAR const struct reginfo_s *reg = &g_tcbinfo.u.reginfo[i]; + uintptr_t value = 0; + + offset = reg->goffset > 0 ? reg->goffset : offset; + ret = gdb_hex2bin(&value, sizeof(value), + state->pkt_buf + offset, state->pkt_len - offset); + if (ret < 0) + { + /* xxxx means to register value not available. */ + + continue; + } + + memcpy(xcpregs + reg->toffset, &value, reg->size); + offset += reg->size; } gdb_send_ok_packet(state); @@ -1121,23 +1161,33 @@ static int gdb_write_registers(FAR struct gdb_state_s *state) static int gdb_read_register(FAR struct gdb_state_s *state) { - uintptr_t addr; + FAR const char *xcpregs = state->xcpregs; + FAR const struct reginfo_s *reg; + uintptr_t value = 0; + uintptr_t regnum; int ret; state->pkt_next++; - ret = gdb_expect_integer(state, &addr); + ret = gdb_expect_integer(state, ®num); if (ret < 0) { return ret; } - if (addr >= state->size) + reg = gdb_find_reginfo(regnum); + if (reg == NULL) { - return 0; + return -EINVAL; + } + + memcpy(&value, xcpregs + reg->toffset, reg->size); + if (ret < 0) + { + return ret; } ret = gdb_bin2hex(state->pkt_buf, sizeof(state->pkt_buf), - &state->registers[addr], sizeof(state->registers[addr])); + &value, reg->size); if (ret < 0) { return ret; @@ -1169,36 +1219,41 @@ static int gdb_read_register(FAR struct gdb_state_s *state) static int gdb_write_register(FAR struct gdb_state_s *state) { - uintptr_t addr; + FAR char *xcpregs = state->xcpregs; + FAR const struct reginfo_s *reg; + uintptr_t value = 0; + uintptr_t regnum; int ret; state->pkt_next++; - ret = gdb_expect_integer(state, &addr); + ret = gdb_expect_integer(state, ®num); if (ret < 0) { return ret; } - ret = gdb_expect_separator(state, '='); - if (ret < 0) + reg = gdb_find_reginfo(regnum); + if (reg == NULL) { - return ret; + return -EINVAL; } - if (addr > state->size / sizeof(uintptr_t) - 1) + ret = gdb_expect_separator(state, '='); + if (ret < 0) { - return -EINVAL; + return ret; } - ret = gdb_hex2bin(&state->registers[addr], sizeof(uintptr_t), + ret = gdb_hex2bin(&value, sizeof(uintptr_t), state->pkt_next, gdb_remaining_len(state)); - if (ret < 0) { return ret; } + memcpy(xcpregs + reg->toffset, &value, reg->size); + gdb_send_ok_packet(state); return 0; } @@ -2018,15 +2073,13 @@ FAR struct gdb_state_s *gdb_state_init(gdb_send_func_t send, gdb_monitor_func_t monitor, FAR void *priv) { - size_t size = g_tcbinfo.regs_num * sizeof(uintptr_t); - FAR struct gdb_state_s *state = lib_zalloc(sizeof(*state) + size); + FAR struct gdb_state_s *state = lib_zalloc(sizeof(struct gdb_state_s)); if (state == NULL) { return NULL; } - state->size = size; state->send = send; state->recv = recv; state->priv = priv; -- Gitee From e8a3d34cf2a7d87362178b277c24f956ad5360f2 Mon Sep 17 00:00:00 2001 From: Neo Xu Date: Wed, 5 Feb 2025 11:29:28 +0800 Subject: [PATCH 228/235] gdbstub: fix memory binary upload on latest GDB VELAPLATFO-52867 GDB release 16.2 recently to fix the incompatibility issue with LLDB. For us, the only change is stub must report it support feature 'binary-upload' before GDB will use this feature. For more information, find bug report and discussion in https://sourceware.org/bugzilla/show_bug.cgi?id=32593 Use GDB 16.2, now it works with binary upload. ``` [remote] Sending packet: $x39c,4#a7 [remote] Received Ack [remote] Packet received: b\000\203 ``` Change-Id: Ic0d69e4127dbaca585b9c2bbd9bb442fd09a3160 Signed-off-by: Neo Xu --- libs/libc/gdbstub/lib_gdbstub.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libs/libc/gdbstub/lib_gdbstub.c b/libs/libc/gdbstub/lib_gdbstub.c index 90b9f4285e8..5499512d968 100644 --- a/libs/libc/gdbstub/lib_gdbstub.c +++ b/libs/libc/gdbstub/lib_gdbstub.c @@ -1497,11 +1497,11 @@ static int gdb_query(FAR struct gdb_state_s *state) { #ifdef CONFIG_ARCH_HAVE_DEBUG state->pkt_len = sprintf(state->pkt_buf, - "hwbreak+;PacketSize=%zx", + "binary-upload+;hwbreak+;PacketSize=%zx", sizeof(state->pkt_buf)); #else state->pkt_len = sprintf(state->pkt_buf, - "PacketSize=%zx", + "binary-upload+;PacketSize=%zx", sizeof(state->pkt_buf)); #endif gdb_send_packet(state); -- Gitee From 296dfbc6eecae30ee5d15424cced8a3cbd9755c7 Mon Sep 17 00:00:00 2001 From: xuxingliang Date: Mon, 10 Feb 2025 09:36:10 +0800 Subject: [PATCH 229/235] jlink: update tcbinfo to access registers. VELAPLATFO-53324 The reg_offs array has been replace by reginfo struct array. Now the JLink NuttX thread awareness is back to work. Register name now uses an 8byte array instead of a pointer to make it have a fixed size. For now, the longest register name is from x86-64: 'eflags' which is 7bytes long, so 8 is enough for now. Exceeding the limit will generate build warning, so we can increase the array size later if needed. Test: make -f Makefile.host jlink-nuttx.so JLinkGDBServer -device stm32f429zi -if SWD -noir -speed 20000K -rtos /nuttx/nuttx/tools/tools/jlink-nuttx.so tools/configure.sh stm32f429i-disco:nsh gdb-multiarch nuttx/nuttx -ex "tar rem:2331" (gdb) info threads Id Target Id Frame * 1.2 Thread 1 ([PID:000]thread-0:0003[PRI:000]) up_idle () at chip/stm32_idle.c:195 1.3 Thread 2 ([PID:001]thread-1:0005[PRI:100]) nxsem_wait_slow (sem=0x20000020 ) at semaphore/sem_wait.c:202 (gdb) Change-Id: Iba028e22c397325c768860a11b3b80011c30714f Signed-off-by: xuxingliang --- include/nuttx/sched.h | 12 ++++++------ tools/jlink-nuttx.c | 45 +++++++++++++++++++++++++------------------ 2 files changed, 32 insertions(+), 25 deletions(-) diff --git a/include/nuttx/sched.h b/include/nuttx/sched.h index e082ab39128..808b84bde9d 100644 --- a/include/nuttx/sched.h +++ b/include/nuttx/sched.h @@ -810,12 +810,12 @@ struct pthread_tcb_s begin_packed_struct struct reginfo_s { - FAR const char *name; /* Register name, must follow GDB, normally in lowercase */ - uint8_t size; /* Register size in bytes */ - uint8_t regnum; /* Remote register number as seen by GDB */ - int16_t toffset; /* Register byte offset in context registers. */ - /* value of REGINFO_OFFSET_INVALID: This register is not provided by NuttX */ - int16_t goffset; /* Register byte offset in g/G packet, default to 0 that means register in order. */ + const char name[8]; /* Register name, must follow GDB, normally in lowercase */ + uint8_t size; /* Register size in bytes */ + uint8_t regnum; /* Remote register number as seen by GDB */ + int16_t toffset; /* Register byte offset in context registers. */ + /* value of REGINFO_OFFSET_INVALID: This register is not provided by NuttX */ + int16_t goffset; /* Register byte offset in g/G packet, default to 0 that means register in order. */ } end_packed_struct; /* struct tcbinfo_s *********************************************************/ diff --git a/tools/jlink-nuttx.c b/tools/jlink-nuttx.c index 713e0507ffc..b112ac58cd8 100644 --- a/tools/jlink-nuttx.c +++ b/tools/jlink-nuttx.c @@ -61,6 +61,11 @@ #define PERROR g_plugin_priv.jops->erroroutf #define PLOG g_plugin_priv.jops->logoutf +/* Macros for special NuttX offset value */ + +#define REGINFO_OFFSET_INVALID -2 +#define REGINFO_OFFSET_AUTO -1 + /* GCC specific definitions */ #ifdef __GNUC__ @@ -89,10 +94,20 @@ enum symbol_e PIDHASH = 0, NPIDHASH, TCBINFO, + REGINFO, READYTORUN, NSYMBOLS }; +begin_packed_struct struct reginfo_s +{ + const char name[8]; + uint8_t size; + uint8_t regnum; + int16_t toffset; + int16_t goffset; +} end_packed_struct; + begin_packed_struct struct tcbinfo_s { uint16_t pid_off; @@ -103,14 +118,12 @@ begin_packed_struct struct tcbinfo_s uint16_t stack_size_off; uint16_t regs_off; uint16_t regs_num; - begin_packed_struct union { uint8_t u[8]; - uint16_t *p; - } - end_packed_struct reg_off; - uint16_t reg_offs[0]; + struct reginfo_s *reginfo; + } u; + struct reginfo_s reginfo[0]; } end_packed_struct; struct symbols_s @@ -177,6 +190,7 @@ static struct symbols_s g_symbols[] = {"g_pidhash", 0, 0}, {"g_npidhash", 0, 0}, {"g_tcbinfo", 0, 0}, + {"g_reginfo", 0, 0}, {"g_readytorun", 0, 0}, { NULL, 0, 0} }; @@ -260,7 +274,7 @@ static int setget_reg(struct plugin_priv_s *priv, uint32_t idx, return -EINVAL; } - if (priv->tcbinfo->reg_offs[regidx] == UINT16_MAX) + if (priv->tcbinfo->reginfo[regidx].toffset == REGINFO_OFFSET_INVALID) { if (write == 0) { @@ -270,7 +284,7 @@ static int setget_reg(struct plugin_priv_s *priv, uint32_t idx, return 0; } - regaddr = priv->regsaddr[idx] + priv->tcbinfo->reg_offs[regidx]; + regaddr = priv->regsaddr[idx] + priv->tcbinfo->reginfo[regidx].toffset; if (write) { @@ -310,16 +324,8 @@ static int update_tcbinfo(struct plugin_priv_s *priv) return -EIO; } - ret = READU32(g_symbols[TCBINFO].address + - offsetof(struct tcbinfo_s, reg_off), ®_off); - if (ret != 0) - { - PERROR("error in read regoffs address ret %d\n", ret); - return ret; - } - priv->tcbinfo = ALLOC(sizeof(struct tcbinfo_s) + - regs_num * sizeof(uint16_t)); + regs_num * sizeof(struct reginfo_s)); if (!priv->tcbinfo) { @@ -335,9 +341,10 @@ static int update_tcbinfo(struct plugin_priv_s *priv) return ret; } - ret = READMEM(reg_off, (char *)&priv->tcbinfo->reg_offs[0], - regs_num * sizeof(uint16_t)); - if (ret != regs_num * sizeof(uint16_t)) + ret = READMEM(g_symbols[REGINFO].address, + (char *)&priv->tcbinfo->reginfo[0], + regs_num * sizeof(struct reginfo_s)); + if (ret != regs_num * sizeof(struct reginfo_s)) { PERROR("error in read tcbinfo_s reg_offs ret %d\n", ret); return ret; -- Gitee From bfc09a75f1c4a6341f149ddb85a7187deda8f16a Mon Sep 17 00:00:00 2001 From: yangao1 Date: Thu, 20 Feb 2025 15:58:43 +0800 Subject: [PATCH 230/235] sched: manually align tcbinfo/reginfo to 64bytes VELAPLATFO-52907 For tasking compiler the `packed` struct debug info is not recogonized correctly in tricore-gdb. Since we can manually align to 64byte, remove the packed attribute. Change-Id: I5a108aa7f8f1c72ecf8c5394d79b93f5a71258bf Signed-off-by: yangao1 --- include/nuttx/sched.h | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/include/nuttx/sched.h b/include/nuttx/sched.h index 808b84bde9d..708ef839170 100644 --- a/include/nuttx/sched.h +++ b/include/nuttx/sched.h @@ -808,7 +808,7 @@ struct pthread_tcb_s * values in tcb context. */ -begin_packed_struct struct reginfo_s +struct reginfo_s { const char name[8]; /* Register name, must follow GDB, normally in lowercase */ uint8_t size; /* Register size in bytes */ @@ -816,7 +816,8 @@ begin_packed_struct struct reginfo_s int16_t toffset; /* Register byte offset in context registers. */ /* value of REGINFO_OFFSET_INVALID: This register is not provided by NuttX */ int16_t goffset; /* Register byte offset in g/G packet, default to 0 that means register in order. */ -} end_packed_struct; + uint16_t reserved; /* in order to alignment in 64bytes */ +}; /* struct tcbinfo_s *********************************************************/ @@ -824,7 +825,7 @@ begin_packed_struct struct reginfo_s * debuggers to parse the tcb information */ -begin_packed_struct struct tcbinfo_s +struct tcbinfo_s { uint16_t pid_off; /* Offset of tcb.pid */ uint16_t state_off; /* Offset of tcb.task_state */ @@ -839,7 +840,7 @@ begin_packed_struct struct tcbinfo_s uint8_t u[8]; FAR const struct reginfo_s *reginfo; /* Register information */ } u; -} end_packed_struct; +}; /* This is the callback type used by nxsched_foreach() */ -- Gitee From 129b939a0784568cafd62c4ce365e6a61c45cd13 Mon Sep 17 00:00:00 2001 From: xuxingliang Date: Tue, 29 Apr 2025 12:15:56 +0800 Subject: [PATCH 231/235] nxgdb: fix wrong backtrace tuple size of memleak VELAPLATFO-57486 Signed-off-by: xuxingliang --- tools/pynuttx/nxgdb/memleak.py | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/tools/pynuttx/nxgdb/memleak.py b/tools/pynuttx/nxgdb/memleak.py index e4e2a47dd2b..8cd131260b9 100644 --- a/tools/pynuttx/nxgdb/memleak.py +++ b/tools/pynuttx/nxgdb/memleak.py @@ -228,15 +228,7 @@ class MMLeak(gdb.Command): } if mm.CONFIG_MM_BACKTRACE and node.backtrace and node.backtrace[0]: - bt = utils.Backtrace(node.backtrace) - info["backtrace"] = [ - { - "address": addr, - "function": func, - "source": source, - } - for addr, func, source in bt.backtrace - ] + info["backtrace"] = utils.Backtrace(node.backtrace) data.append(info) return { -- Gitee From 05bf37fc3fdc4ce4f459827361f33148665ce12e Mon Sep 17 00:00:00 2001 From: xuxingliang Date: Mon, 28 Apr 2025 18:17:05 +0800 Subject: [PATCH 232/235] nxgdb: fix jsonify backtrace VELAPLATFO-42403 The backtrace is now 4 elements including address, function, source and line. Exception in this function is silently ignored and obj.__dict__ is used in jsonify function. Change-Id: I5299eb97ed95a66d7528a978b0f9b52d1a4284d0 Signed-off-by: xuxingliang --- tools/pynuttx/nxgdb/utils.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tools/pynuttx/nxgdb/utils.py b/tools/pynuttx/nxgdb/utils.py index e54a60049bc..b04d5200afd 100644 --- a/tools/pynuttx/nxgdb/utils.py +++ b/tools/pynuttx/nxgdb/utils.py @@ -244,7 +244,7 @@ class Backtrace: for addr in address: if break_null and not addr: break - self.append(addr) + self.append(int(addr)) def __eq__(self, value: Backtrace) -> bool: return self.backtrace == value.backtrace @@ -286,8 +286,8 @@ class Backtrace: def toJSON(self): return [ - {"address": addr, "function": func, "source": source} - for addr, func, source in self.backtrace + {"address": addr, "function": func, "source": source, "line": line} + for addr, func, source, line in self.backtrace ] -- Gitee From 76c55a540d1b7363e233c7b5b69666d884b4cd3e Mon Sep 17 00:00:00 2001 From: yinshengkai Date: Mon, 28 Apr 2025 16:48:11 +0800 Subject: [PATCH 233/235] nxgdb: fix wrong backtrace tuple size VELAPLATFO-57486 Change-Id: If27f8b704a8ee20ad0b1aa9031aae848da9ad7dc Signed-off-by: yinshengkai --- tools/pynuttx/nxgdb/memclassify.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tools/pynuttx/nxgdb/memclassify.py b/tools/pynuttx/nxgdb/memclassify.py index d954bf24898..bc6b81f638b 100644 --- a/tools/pynuttx/nxgdb/memclassify.py +++ b/tools/pynuttx/nxgdb/memclassify.py @@ -246,11 +246,11 @@ class MemBlockCoredump(MemBlock): self.cnt = cnt # deal with call_stack self.call_stack = [] - for addr, func, file in utils.Backtrace(node.backtrace).backtrace: + for addr, func, file, line in utils.Backtrace(node.backtrace).backtrace: func = func.strip("<>") if func.find("+"): # remove the offset affter '+' func = func[: func.find("+")] - self.call_stack.append((func, file)) + self.call_stack.append((func, f"{file}:{line}")) def total_size(self): return self.mem_node.nodesize * self.cnt -- Gitee From c483f1c5dbe55fabf0dea81641b3e594f2bef26b Mon Sep 17 00:00:00 2001 From: yinshengkai Date: Mon, 28 Apr 2025 16:56:45 +0800 Subject: [PATCH 234/235] nxtrace: fix cannot import name 'PerfettoTraceBadArgsError' from 'nxtrace' VELAPLATFO-55359 Change-Id: Ie0298163f57a42c5e83ada82d6466ba35b1b2ee5 Signed-off-by: yinshengkai --- tools/pynuttx/nxtrace/perfetto_trace.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/tools/pynuttx/nxtrace/perfetto_trace.py b/tools/pynuttx/nxtrace/perfetto_trace.py index 11e302ed763..81155768384 100644 --- a/tools/pynuttx/nxtrace/perfetto_trace.py +++ b/tools/pynuttx/nxtrace/perfetto_trace.py @@ -28,7 +28,6 @@ except ImportError: print("pip install protobuf==4.25.3") exit(1) -from . import PerfettoTraceBadArgsError from . import perfetto_trace_pb2 as pb2 logger = logging.getLogger(__name__) @@ -74,6 +73,10 @@ class TraceHead: self.tid = tid if tid is not None else pid +class PerfettoTraceBadArgsError(ValueError): + pass + + class TraceClassFactory: def __new__(cls, message_name): message_descriptor = cls._get_message_descriptor(message_name) -- Gitee From 6b59cf762ba17f942a2ca4f0ee21448fae668f70 Mon Sep 17 00:00:00 2001 From: xuxingliang Date: Thu, 15 May 2025 21:45:37 +0800 Subject: [PATCH 235/235] pynuttx: fix style issue reported on ubuntu24.04 Signed-off-by: xuxingliang --- tools/pynuttx/nxgdb/fs.py | 2 +- tools/pynuttx/nxgdb/memdump.py | 4 +++- tools/pynuttx/nxreg/register.py | 2 +- tools/pynuttx/nxtrace/rtt.py | 3 ++- 4 files changed, 7 insertions(+), 4 deletions(-) diff --git a/tools/pynuttx/nxgdb/fs.py b/tools/pynuttx/nxgdb/fs.py index 68c868454bb..f8edbd9c24b 100644 --- a/tools/pynuttx/nxgdb/fs.py +++ b/tools/pynuttx/nxgdb/fs.py @@ -688,7 +688,7 @@ class InfoYaffs(gdb.Command): f"n_data_chunks:{n_data_chunks},serial:{serial}{moreinfo}" } - print(f"{initial_indent}{file_type.rsplit('_',2)[1]} {baseinfo}") + print(f"{initial_indent}{file_type.rsplit('_', 2)[1]} {baseinfo}") if file_type == "yaffs_dir_var": head = node.variant.cast(utils.lookup_type("struct yaffs_dir_var")) for siblings in NxList(head.children, "struct yaffs_obj", "siblings"): diff --git a/tools/pynuttx/nxgdb/memdump.py b/tools/pynuttx/nxgdb/memdump.py index 07961fd0a51..9720a007ec1 100644 --- a/tools/pynuttx/nxgdb/memdump.py +++ b/tools/pynuttx/nxgdb/memdump.py @@ -761,7 +761,9 @@ class NxMemoryRange(gdb.Command): print(formatter.format(*header)) for start, end in memrange: length = end - start - print(formatter.format(hex(start), hex(end), length, f"{length/1024: .1f}")) + print( + formatter.format(hex(start), hex(end), length, f"{length / 1024: .1f}") + ) class NxDumpRAM(gdb.Command): diff --git a/tools/pynuttx/nxreg/register.py b/tools/pynuttx/nxreg/register.py index 1c0daf2951c..db03cc3f915 100644 --- a/tools/pynuttx/nxreg/register.py +++ b/tools/pynuttx/nxreg/register.py @@ -508,7 +508,7 @@ class GeneralRegisters: for reg in self._registers: goffset = reg.goffset self.logger.debug( - f"Parse {reg.name}({reg.regnum}) from {goffset}, data: {data[goffset:goffset+reg.size]}" + f"Parse {reg.name}({reg.regnum}) from {goffset}, data: {data[goffset:goffset + reg.size]}" ) reg.value = data[goffset : goffset + reg.size] goffset = reg.goffset + reg.size diff --git a/tools/pynuttx/nxtrace/rtt.py b/tools/pynuttx/nxtrace/rtt.py index b9e518e4a13..777cb4eb362 100644 --- a/tools/pynuttx/nxtrace/rtt.py +++ b/tools/pynuttx/nxtrace/rtt.py @@ -108,7 +108,8 @@ class SeggerRTT: last_time = now_time last_receive_total = self.receive_total logger.debug( - f"Receive rate: {self.receive_rate/1024:.2f} KB/s, total: {self.receive_total/1024/1024:.2f} MB" + f"Receive rate: {self.receive_rate / 1024:.2f} KB/s, " + f"total: {self.receive_total / 1024 / 1024:.2f} MB" ) self.receive_total += len(data) -- Gitee