Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
54 changes: 0 additions & 54 deletions .ruff-excludes.toml
Original file line number Diff line number Diff line change
Expand Up @@ -128,57 +128,14 @@
"I001", # https://docs.astral.sh/ruff/rules/unsorted-imports
"UP015", # https://docs.astral.sh/ruff/rules/redundant-open-modes
]
"./scripts/coredump/coredump_gdbserver.py" = [
"I001", # https://docs.astral.sh/ruff/rules/unsorted-imports
]
"./scripts/coredump/coredump_parser/elf_parser.py" = [
"E501", # https://docs.astral.sh/ruff/rules/line-too-long
"I001", # https://docs.astral.sh/ruff/rules/unsorted-imports
"SIM115", # https://docs.astral.sh/ruff/rules/open-file-with-context-handler
"UP031", # https://docs.astral.sh/ruff/rules/printf-string-formatting
"UP039", # https://docs.astral.sh/ruff/rules/unnecessary-class-parentheses
]
"./scripts/coredump/coredump_parser/log_parser.py" = [
"I001", # https://docs.astral.sh/ruff/rules/unsorted-imports
"SIM115", # https://docs.astral.sh/ruff/rules/open-file-with-context-handler
"UP030", # https://docs.astral.sh/ruff/rules/format-literals
"UP031", # https://docs.astral.sh/ruff/rules/printf-string-formatting
"UP032", # https://docs.astral.sh/ruff/rules/f-string
]
"./scripts/coredump/coredump_serial_log_parser.py" = [
"I001", # https://docs.astral.sh/ruff/rules/unsorted-imports
"SIM115", # https://docs.astral.sh/ruff/rules/open-file-with-context-handler
"UP015", # https://docs.astral.sh/ruff/rules/redundant-open-modes
]
"./scripts/coredump/gdbstubs/arch/arm64.py" = [
"I001", # https://docs.astral.sh/ruff/rules/unsorted-imports
"UP039", # https://docs.astral.sh/ruff/rules/unnecessary-class-parentheses
]
"./scripts/coredump/gdbstubs/arch/arm_cortex_m.py" = [
"E501", # https://docs.astral.sh/ruff/rules/line-too-long
"I001", # https://docs.astral.sh/ruff/rules/unsorted-imports
"UP039", # https://docs.astral.sh/ruff/rules/unnecessary-class-parentheses
]
"./scripts/coredump/gdbstubs/arch/risc_v.py" = [
"I001", # https://docs.astral.sh/ruff/rules/unsorted-imports
"UP039", # https://docs.astral.sh/ruff/rules/unnecessary-class-parentheses
]
"./scripts/coredump/gdbstubs/arch/x86.py" = [
"I001", # https://docs.astral.sh/ruff/rules/unsorted-imports
"UP039", # https://docs.astral.sh/ruff/rules/unnecessary-class-parentheses
]
"./scripts/coredump/gdbstubs/arch/x86_64.py" = [
"I001", # https://docs.astral.sh/ruff/rules/unsorted-imports
"UP039", # https://docs.astral.sh/ruff/rules/unnecessary-class-parentheses
]
"./scripts/coredump/gdbstubs/arch/xtensa.py" = [
"I001", # https://docs.astral.sh/ruff/rules/unsorted-imports
"SIM113", # https://docs.astral.sh/ruff/rules/enumerate-for-loop
"UP031", # https://docs.astral.sh/ruff/rules/printf-string-formatting
]
"./scripts/coredump/gdbstubs/gdbstub.py" = [
"E501", # https://docs.astral.sh/ruff/rules/line-too-long
"I001", # https://docs.astral.sh/ruff/rules/unsorted-imports
]
"./scripts/dts/gen_defines.py" = [
"B007", # https://docs.astral.sh/ruff/rules/unused-loop-control-variable
Expand Down Expand Up @@ -965,17 +922,6 @@ exclude = [
"./samples/subsys/zbus/remote_mock/remote_mock.py",
"./scripts/check_maintainers.py",
"./scripts/ci/upload_test_results_es.py",
"./scripts/coredump/coredump_gdbserver.py",
"./scripts/coredump/coredump_parser/elf_parser.py",
"./scripts/coredump/coredump_parser/log_parser.py",
"./scripts/coredump/coredump_serial_log_parser.py",
"./scripts/coredump/gdbstubs/arch/arm64.py",
"./scripts/coredump/gdbstubs/arch/arm_cortex_m.py",
"./scripts/coredump/gdbstubs/arch/risc_v.py",
"./scripts/coredump/gdbstubs/arch/x86.py",
"./scripts/coredump/gdbstubs/arch/x86_64.py",
"./scripts/coredump/gdbstubs/arch/xtensa.py",
"./scripts/coredump/gdbstubs/gdbstub.py",
"./scripts/dts/gen_defines.py",
"./scripts/dts/gen_driver_kconfig_dts.py",
"./scripts/dts/gen_dts_cmake.py",
Expand Down
17 changes: 6 additions & 11 deletions scripts/coredump/coredump_gdbserver.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,9 @@
import socket
import sys

from coredump_parser.log_parser import CoredumpLogFile
from coredump_parser.elf_parser import CoredumpElfFile

import gdbstubs
from coredump_parser.elf_parser import CoredumpElfFile
from coredump_parser.log_parser import CoredumpLogFile

LOGGING_FORMAT = "[%(levelname)s][%(name)s] %(message)s"

Expand Down Expand Up @@ -43,14 +42,10 @@ def parse_args():

parser.add_argument("elffile", help="Zephyr ELF binary")
parser.add_argument("logfile", help="Coredump binary log file")
parser.add_argument("--debug", action="store_true",
help="Print extra debugging information")
parser.add_argument("--port", type=int, default=1234,
help="GDB server port")
parser.add_argument("--pipe", action="store_true",
help="Use stdio to communicate with gdb")
parser.add_argument("-v", "--verbose", action="store_true",
help="Print more information")
parser.add_argument("--debug", action="store_true", help="Print extra debugging information")
parser.add_argument("--port", type=int, default=1234, help="GDB server port")
parser.add_argument("--pipe", action="store_true", help="Use stdio to communicate with gdb")
parser.add_argument("-v", "--verbose", action="store_true", help="Print more information")

return parser.parse_args()

Expand Down
82 changes: 58 additions & 24 deletions scripts/coredump/coredump_parser/elf_parser.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,10 @@

import logging
import struct
from enum import IntEnum

import elftools
from elftools.elf.elffile import ELFFile
from enum import IntEnum


# ELF section flags
SHF_WRITE = 0x1
Expand All @@ -19,6 +18,7 @@
SHF_WRITE_ALLOC = SHF_WRITE | SHF_ALLOC
SHF_ALLOC_EXEC = SHF_ALLOC | SHF_EXEC


# Must match enum in thread_info.c
class ThreadInfoOffset(IntEnum):
THREAD_INFO_OFFSET_VERSION = 0
Expand All @@ -44,7 +44,7 @@ def __int__(self):
logger = logging.getLogger("parser")


class CoredumpElfFile():
class CoredumpElfFile:
"""
Class to parse ELF file for memory content in various sections.
There are read-only sections (e.g. text and rodata) where
Expand Down Expand Up @@ -78,7 +78,11 @@ def has_kernel_thread_info(self):
return self.kernel_thread_info_offsets is not None

def get_kernel_thread_info_offset(self, thread_info_offset_index):
if self.has_kernel_thread_info() and thread_info_offset_index <= ThreadInfoOffset.THREAD_INFO_OFFSET_T_ARC_RELINQUISH_CAUSE:
if (
self.has_kernel_thread_info()
and thread_info_offset_index
<= ThreadInfoOffset.THREAD_INFO_OFFSET_T_ARC_RELINQUISH_CAUSE
):
return self.kernel_thread_info_offsets[thread_info_offset_index]
else:
return None
Expand All @@ -96,14 +100,20 @@ def parse(self):
for section in self.elf.iter_sections():
# Find symbols for _kernel_thread_info data
if isinstance(section, elftools.elf.sections.SymbolTableSection):
_kernel_thread_info_offsets = section.get_symbol_by_name("_kernel_thread_info_offsets")
_kernel_thread_info_num_offsets = section.get_symbol_by_name("_kernel_thread_info_num_offsets")
_kernel_thread_info_size_t_size = section.get_symbol_by_name("_kernel_thread_info_size_t_size")
_kernel_thread_info_offsets = section.get_symbol_by_name(
"_kernel_thread_info_offsets"
)
_kernel_thread_info_num_offsets = section.get_symbol_by_name(
"_kernel_thread_info_num_offsets"
)
_kernel_thread_info_size_t_size = section.get_symbol_by_name(
"_kernel_thread_info_size_t_size"
)

# REALLY NEED to match exact type as all other sections
# (debug, text, etc.) are descendants where
# isinstance() would match.
if type(section) is not elftools.elf.sections.Section: # pylint: disable=unidiomatic-typecheck
if type(section) is not elftools.elf.sections.Section: # pylint: disable=unidiomatic-typecheck
continue

size = section['sh_size']
Expand Down Expand Up @@ -132,56 +142,80 @@ def parse(self):

if store:
mem_region = {"start": sec_start, "end": sec_end, "data": section.data()}
logger.info("ELF Section: 0x%x to 0x%x of size %d (%s)" %
(mem_region["start"],
mem_region["end"],
len(mem_region["data"]),
sect_desc))
logger.info(
f'ELF Section: 0x{mem_region["start"]:x} to 0x{mem_region["end"]:x} '
f'of size {mem_region["data"]:d} ({sect_desc:s})'
)

self.memory_regions.append(mem_region)

if _kernel_thread_info_size_t_size is not None and \
_kernel_thread_info_num_offsets is not None and \
_kernel_thread_info_offsets is not None:
if (
_kernel_thread_info_size_t_size is not None
and _kernel_thread_info_num_offsets is not None
and _kernel_thread_info_offsets is not None
):
for seg in self.elf.iter_segments():
if seg.header['p_type'] != 'PT_LOAD':
continue

# Store segment of kernel_thread_info_offsets
info_offsets_symbol = _kernel_thread_info_offsets[0]
if info_offsets_symbol['st_value'] >= seg['p_vaddr'] and info_offsets_symbol['st_value'] < seg['p_vaddr'] + seg['p_filesz']:
if (
info_offsets_symbol['st_value'] >= seg['p_vaddr']
and info_offsets_symbol['st_value'] < seg['p_vaddr'] + seg['p_filesz']
):
kernel_thread_info_offsets_segment = seg

# Store segment of kernel_thread_info_num_offsets
num_offsets_symbol = _kernel_thread_info_num_offsets[0]
if num_offsets_symbol['st_value'] >= seg['p_vaddr'] and num_offsets_symbol['st_value'] < seg['p_vaddr'] + seg['p_filesz']:
if (
num_offsets_symbol['st_value'] >= seg['p_vaddr']
and num_offsets_symbol['st_value'] < seg['p_vaddr'] + seg['p_filesz']
):
kernel_thread_info_num_offsets_segment = seg

# Read and store size_t size
size_t_size_symbol = _kernel_thread_info_size_t_size[0]
if size_t_size_symbol['st_value'] >= seg['p_vaddr'] and size_t_size_symbol['st_value'] < seg['p_vaddr'] + seg['p_filesz']:
if (
size_t_size_symbol['st_value'] >= seg['p_vaddr']
and size_t_size_symbol['st_value'] < seg['p_vaddr'] + seg['p_filesz']
):
offset = size_t_size_symbol['st_value'] - seg['p_vaddr'] + seg['p_offset']
self.elf.stream.seek(offset)
self.kernel_thread_info_size_t_size = struct.unpack('B', self.elf.stream.read(size_t_size_symbol['st_size']))[0]
self.kernel_thread_info_size_t_size = struct.unpack(
'B', self.elf.stream.read(size_t_size_symbol['st_size'])
)[0]

struct_format = "I"
if self.kernel_thread_info_size_t_size == 8:
struct_format = "Q"

# Read and store count of offset values
num_offsets_symbol = _kernel_thread_info_num_offsets[0]
offset = num_offsets_symbol['st_value'] - kernel_thread_info_num_offsets_segment['p_vaddr'] + kernel_thread_info_num_offsets_segment['p_offset']
offset = (
num_offsets_symbol['st_value']
- kernel_thread_info_num_offsets_segment['p_vaddr']
+ kernel_thread_info_num_offsets_segment['p_offset']
)
self.elf.stream.seek(offset)
self.kernel_thread_info_num_offsets = struct.unpack(struct_format, self.elf.stream.read(num_offsets_symbol['st_size']))[0]
self.kernel_thread_info_num_offsets = struct.unpack(
struct_format, self.elf.stream.read(num_offsets_symbol['st_size'])
)[0]

array_format = ""
for _ in range(self.kernel_thread_info_num_offsets):
array_format = array_format + struct_format

# Read and store array of offset values
info_offsets_symbol = _kernel_thread_info_offsets[0]
offset = info_offsets_symbol['st_value'] - kernel_thread_info_offsets_segment['p_vaddr'] + kernel_thread_info_offsets_segment['p_offset']
offset = (
info_offsets_symbol['st_value']
- kernel_thread_info_offsets_segment['p_vaddr']
+ kernel_thread_info_offsets_segment['p_offset']
)
self.elf.stream.seek(offset)
self.kernel_thread_info_offsets = struct.unpack(array_format, self.elf.stream.read(info_offsets_symbol['st_size']))
self.kernel_thread_info_offsets = struct.unpack(
array_format, self.elf.stream.read(info_offsets_symbol['st_size'])
)

return True
30 changes: 14 additions & 16 deletions scripts/coredump/coredump_parser/log_parser.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@
import logging
import struct


# Note: keep sync with C code
COREDUMP_HDR_ID = b'ZE'
COREDUMP_HDR_VER = 2
Expand Down Expand Up @@ -62,7 +61,7 @@ def __init__(self, logfile):
self.log_hdr = None
self.arch_data = list()
self.memory_regions = list()
self.threads_metadata = {"hdr_ver" : None, "data" : None}
self.threads_metadata = {"hdr_ver": None, "data": None}

def open(self):
self.fd = open(self.logfile, "rb")
Expand All @@ -85,7 +84,7 @@ def parse_arch_section(self):

arch_data = self.fd.read(num_bytes)

self.arch_data = {"hdr_ver" : hdr_ver, "data" : arch_data}
self.arch_data = {"hdr_ver": hdr_ver, "data": arch_data}

return True

Expand All @@ -95,7 +94,7 @@ def parse_threads_metadata_section(self):

data = self.fd.read(num_bytes)

self.threads_metadata = {"hdr_ver" : hdr_ver, "data" : data}
self.threads_metadata = {"hdr_ver": hdr_ver, "data": data}

return True

Expand Down Expand Up @@ -126,8 +125,7 @@ def parse_memory_section(self):
mem = {"start": saddr, "end": eaddr, "data": data}
self.memory_regions.append(mem)

logger.info("Memory: 0x%x to 0x%x of size %d" %
(saddr, eaddr, size))
logger.info(f"Memory: 0x{saddr:x} to 0x{eaddr:x} of size {size:d}")

return True

Expand All @@ -147,17 +145,17 @@ def parse(self):
logger.error(f"Log version: {hdr_ver}, expected: {COREDUMP_HDR_VER}!")
return False

ptr_size = 2 ** ptr_size
ptr_size = 2**ptr_size

self.log_hdr = {
"hdr_version": hdr_ver,
"tgt_code": tgt_code,
"ptr_size": ptr_size,
"flags": flags,
"reason": reason,
}

logger.info("Reason: {0}".format(reason_string(reason)))
"hdr_version": hdr_ver,
"tgt_code": tgt_code,
"ptr_size": ptr_size,
"flags": flags,
"reason": reason,
}

logger.info(f"Reason: {reason_string(reason)}")
logger.info(f"Pointer size {ptr_size}")

del id1, id2, hdr_ver, tgt_code, ptr_size, flags, reason
Expand All @@ -168,7 +166,7 @@ def parse(self):
# no more data to read
break

self.fd.seek(-1, 1) # go back 1 byte
self.fd.seek(-1, 1) # go back 1 byte
if section_id == COREDUMP_ARCH_HDR_ID:
if not self.parse_arch_section():
logger.error("Cannot parse architecture section")
Expand Down
6 changes: 2 additions & 4 deletions scripts/coredump/coredump_serial_log_parser.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@
import binascii
import sys


COREDUMP_PREFIX_STR = "#CD:"

COREDUMP_BEGIN_STR = COREDUMP_PREFIX_STR + "BEGIN#"
Expand All @@ -20,16 +19,15 @@ def parse_args():
parser = argparse.ArgumentParser(allow_abbrev=False)

parser.add_argument("infile", help="Serial Log File")
parser.add_argument("outfile",
help="Output file for use with coredump GDB server")
parser.add_argument("outfile", help="Output file for use with coredump GDB server")

return parser.parse_args()


def main():
args = parse_args()

infile = open(args.infile, "r")
infile = open(args.infile)
if not infile:
print(f"ERROR: Cannot open input file: {args.infile}, exiting...")
sys.exit(1)
Expand Down
Loading
Loading