diff --git a/include/arch/arc/v2/linker.ld b/include/arch/arc/v2/linker.ld index 51a19b86d0b..5ff94fac209 100644 --- a/include/arch/arc/v2/linker.ld +++ b/include/arch/arc/v2/linker.ld @@ -71,6 +71,8 @@ SECTIONS { KEEP(*(.exc_vector_table)) KEEP(*(".exc_vector_table.*")) + KEEP(*(.openocd_dbg)) + KEEP(*(".openocd_dbg.*")) KEEP(*(IRQ_VECTOR_TABLE)) diff --git a/include/arch/arm/cortex_m/scripts/linker.ld b/include/arch/arm/cortex_m/scripts/linker.ld index 9d8d2561da7..8bfc57adda8 100644 --- a/include/arch/arm/cortex_m/scripts/linker.ld +++ b/include/arch/arm/cortex_m/scripts/linker.ld @@ -82,6 +82,9 @@ SECTIONS KEEP(*(IRQ_VECTOR_TABLE)) + KEEP(*(.openocd_dbg)) + KEEP(*(".openocd_dbg.*")) + /* Kinetis has to write 16 bytes at 0x400 */ SKIP_TO_KINETIS_FLASH_CONFIG KEEP(*(.kinetis_flash_config)) diff --git a/include/arch/nios2/linker.ld b/include/arch/nios2/linker.ld index 4f75c2fc3e5..c63728da837 100644 --- a/include/arch/nios2/linker.ld +++ b/include/arch/nios2/linker.ld @@ -107,6 +107,8 @@ SECTIONS *(.text) *(".text.*") *(.gnu.linkonce.t.*) + KEEP(*(.openocd_dbg)) + KEEP(*(".openocd_dbg.*")) } GROUP_LINK_IN(ROMABLE_REGION) _image_text_end = .; diff --git a/include/arch/riscv32/common/linker.ld b/include/arch/riscv32/common/linker.ld index fd248abac6d..81dd91becbd 100644 --- a/include/arch/riscv32/common/linker.ld +++ b/include/arch/riscv32/common/linker.ld @@ -81,6 +81,9 @@ SECTIONS /* sections for IRQ100-999 */ KEEP(*(SORT(.gnu.linkonce.isr_irq[0-9][0-9][0-9]))) + KEEP(*(.openocd_debug)) + KEEP(*(".openocd_debug.*")) + _image_text_start = .; *(.text) *(".text.*") diff --git a/include/arch/riscv32/pulpino/linker.ld b/include/arch/riscv32/pulpino/linker.ld index 74bd69c8bfe..f0005e2e228 100644 --- a/include/arch/riscv32/pulpino/linker.ld +++ b/include/arch/riscv32/pulpino/linker.ld @@ -60,6 +60,9 @@ SECTIONS { . = ALIGN(4); + KEEP(*(.openocd_dbg)) + KEEP(*(".openocd_dbg.*")) + _image_text_start = .; *(.text) *(".text.*") diff --git a/include/arch/x86/linker.ld b/include/arch/x86/linker.ld index 97e5bf2a79d..1427e8b517b 100644 --- a/include/arch/x86/linker.ld +++ b/include/arch/x86/linker.ld @@ -76,6 +76,8 @@ SECTIONS *(.init) *(.fini) *(.eini) + KEEP(*(.openocd_dbg)) + KEEP(*(".openocd_dbg.*")) KEXEC_PGALIGN_PAD(MMU_PAGE_SIZE) } GROUP_LINK_IN(ROMABLE_REGION) diff --git a/subsys/debug/Kconfig b/subsys/debug/Kconfig index 97b42f808f0..3f20474872d 100644 --- a/subsys/debug/Kconfig +++ b/subsys/debug/Kconfig @@ -115,3 +115,17 @@ config GDB_SERVER_BOOTLOADER depends on GDB_SERVER help This option enables the bootloader mode of the GDB Server. + +# +# Miscellaneous debugging options +# + +config OPENOCD_SUPPORT + bool + prompt "OpenOCD support [EXPERIMENTAL]" + default n + select THREAD_MONITOR + help + This option exports an array of offsets to kernel structs, used by + OpenOCD to determine the state of running threads. (This option + selects CONFIG_THREAD_MONITOR, so all of its caveats are implied.) diff --git a/subsys/debug/Makefile b/subsys/debug/Makefile index f1d2873555f..4fe055e094a 100644 --- a/subsys/debug/Makefile +++ b/subsys/debug/Makefile @@ -4,3 +4,9 @@ CFLAGS_gdb_server.o =-I$(srctree)/include/drivers obj-y = obj-$(CONFIG_MEM_SAFE_CHECK_BOUNDARIES) += mem_safe_check_boundaries.o obj-$(CONFIG_GDB_SERVER) += gdb_server.o + +ifeq ($(CONFIG_OPENOCD_SUPPORT),y) +lib-y += openocd.o +ldflags-y += --undefined=_kernel_openocd_size_t_size +ldflags-y += --undefined=_kernel_openocd_offsets +endif diff --git a/subsys/debug/openocd.c b/subsys/debug/openocd.c new file mode 100644 index 00000000000..c0dbf51ae69 --- /dev/null +++ b/subsys/debug/openocd.c @@ -0,0 +1,67 @@ +/* + * Copyright (c) 2017 Intel Corporation + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include + +#if defined(CONFIG_OPENOCD_SUPPORT) && defined(CONFIG_THREAD_MONITOR) +enum { + OPENOCD_OFFSET_VERSION, + OPENOCD_OFFSET_K_CURR_THREAD, + OPENOCD_OFFSET_K_THREADS, + OPENOCD_OFFSET_T_ENTRY, + OPENOCD_OFFSET_T_NEXT_THREAD, + OPENOCD_OFFSET_T_STATE, + OPENOCD_OFFSET_T_USER_OPTIONS, + OPENOCD_OFFSET_T_PRIO, + OPENOCD_OFFSET_T_STACK_PTR, +}; + +/* Forward-compatibility notes: 1) Increment OPENOCD_OFFSET_VERSION element + * each time an offset is added to this table. 2) Only append items to this + * table; otherwise, OpenOCD versions that expects version 0 will read garbage + * values. + */ +__attribute__((used, section(".openocd_dbg"))) +size_t _kernel_openocd_offsets[] = { + /* Version 0 starts */ + [OPENOCD_OFFSET_VERSION] = 0, + [OPENOCD_OFFSET_K_CURR_THREAD] = offsetof(struct _kernel, current), + [OPENOCD_OFFSET_K_THREADS] = offsetof(struct _kernel, threads), + [OPENOCD_OFFSET_T_ENTRY] = offsetof(struct k_thread, entry), + [OPENOCD_OFFSET_T_NEXT_THREAD] = offsetof(struct k_thread, next_thread), + [OPENOCD_OFFSET_T_STATE] = offsetof(struct _thread_base, thread_state), + [OPENOCD_OFFSET_T_USER_OPTIONS] = offsetof(struct _thread_base, + user_options), + [OPENOCD_OFFSET_T_PRIO] = offsetof(struct _thread_base, prio), +#if defined(CONFIG_ARM) + [OPENOCD_OFFSET_T_STACK_PTR] = offsetof(struct k_thread, + callee_saved.psp), +#elif defined(CONFIG_ARC) + [OPENOCD_OFFSET_T_STACK_PTR] = offsetof(struct k_thread, + callee_saved.sp), +#elif defined(CONFIG_X86) + [OPENOCD_OFFSET_T_STACK_PTR] = offsetof(struct k_thread, + callee_saved.esp), +#elif defined(CONFIG_NIOS2) + [OPENOCD_OFFSET_T_STACK_PTR] = offsetof(struct k_thread, + callee_saved.sp), +#elif defined(CONFIG_RISCV32) + [OPENOCD_OFFSET_T_STACK_PTR] = offsetof(struct k_thread, + callee_saved.sp), +#else + /* Use 0xffffffff as a special value so that OpenOCD knows that + * obtaining the stack pointer is not possible on this particular + * architecture. + */ +#warning Please define OPENOCD_OFFSET_T_STACK_PTR for this architecture + [OPENOCD_OFFSET_T_STACK_PTR] = 0xffffffff, +#endif + /* Version 0 ends */ +}; + +__attribute__((used, section(".openocd_dbg"))) +uint8_t _kernel_openocd_size_t_size = (uint8_t)sizeof(size_t); +#endif