From 570634a25985db1d66f8ac65f1283762163b7c4d Mon Sep 17 00:00:00 2001 From: Leandro Pereira Date: Wed, 1 Feb 2017 10:21:21 -0800 Subject: [PATCH] kernel: Add OpenOCD support In order for OpenOCD to have a high-level view of an RTOS, it uses the GDB protocol to obtain symbols from the system. The GDB protocol, however, does not allow obtaining fields from structures directly, and hardcoding offsets is not only brittle (due to possibly different architectures or changes in the code), it's also infeasible considering Zephyr is highly-configurable and parts of key structs can be compiled in or out. Export an array with offsets for these key structs. Also add a version element in that array to allow changes in those structs. Change-Id: I83bcfa0a7bd57d85582e5ec6efe70e1cceb1fc51 Signed-off-by: Leandro Pereira --- include/arch/arc/v2/linker.ld | 2 + include/arch/arm/cortex_m/scripts/linker.ld | 3 + include/arch/nios2/linker.ld | 2 + include/arch/riscv32/common/linker.ld | 3 + include/arch/riscv32/pulpino/linker.ld | 3 + include/arch/x86/linker.ld | 2 + subsys/debug/Kconfig | 14 +++++ subsys/debug/Makefile | 6 ++ subsys/debug/openocd.c | 67 +++++++++++++++++++++ 9 files changed, 102 insertions(+) create mode 100644 subsys/debug/openocd.c 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