From b988768f83da0b06bc564d2be135af01d5b2dec8 Mon Sep 17 00:00:00 2001 From: Chris Johns Date: Thu, 26 Mar 2015 17:08:18 +1100 Subject: trace-linker: Add Trace Buffering support. Trace buffering traces into a static buffer complete with timestamp and the executing context. A shell command provides access to the data. --- linkers/rtld-trace-buffer.ini | 171 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 171 insertions(+) create mode 100644 linkers/rtld-trace-buffer.ini (limited to 'linkers/rtld-trace-buffer.ini') diff --git a/linkers/rtld-trace-buffer.ini b/linkers/rtld-trace-buffer.ini new file mode 100644 index 0000000..f018410 --- /dev/null +++ b/linkers/rtld-trace-buffer.ini @@ -0,0 +1,171 @@ +; +; RTEMS Trace Linker Trace Buffer +; +; Copyright 2015 Chris Johns +; + +; +; A trace buffer generator buffers records to a buffer that can be extracted +; latter. +; +[trace-buffer-generator] +headers = trace-buffer-generator-headers +code-blocks = trace-buffer-tracers +lock-local = " rtems_interrupt_lock_context lcontext;" +lock-acquire = " rtems_interrupt_lock_acquire(&__rtld_tbg_lock, &lcontext);" +lock-release = " rtems_interrupt_lock_release(&__rtld_tbg_lock, &lcontext);" +entry-trace = "__rtld_tbg_buffer_entry(&in, @FUNC_INDEX@, RTLD_TBG_REC_OVERHEAD + @FUNC_DATA_ENTRY_SIZE@);" +entry-alloc = "in = __rtld_tbg_buffer_alloc(@FUNC_INDEX@, RTLD_TBG_REC_OVERHEAD + @FUNC_DATA_ENTRY_SIZE@);" +arg-trace = "__rtld_tbg_buffer_arg(&in, @ARG_SIZE@, (void*) &@ARG_LABEL@);" +exit-trace = "__rtld_tbg_buffer_exit(&in, @FUNC_INDEX@, RTLD_TBG_REC_OVERHEAD + @FUNC_DATA_RET_SIZE@);" +exit-alloc = "in = __rtld_tbg_buffer_alloc(@FUNC_INDEX@, RTLD_TBG_REC_OVERHEAD + @FUNC_DATA_RET_SIZE@);" +ret-trace = "__rtld_tbg_buffer_ret(in, @RET_SIZE@, (void*) &@RET_LABEL@);" +buffer-local = " uint8_t* in;" + +[trace-buffer-generator-headers] +header = "#include " +header = "#include " + +[trace-buffer-tracers] +code = <<Object.id; +} + +static inline uint32_t __rtld_tbg_executing_status(void) +{ + /* @fixme Add the current CPU for SMP. */ + return (_Thread_Executing->current_priority << 8) | _Thread_Executing->real_priority; +} + +static inline uint32_t __rtld_tbg_executing_state(void) +{ + return _Thread_Executing->current_state; +} + +static inline bool __rtld_tbg_is_enabled(const uint32_t index) +{ + return (__rtld_trace_enables[index / 32] & (1 << (index & (32 - 1)))) != 0 ? true : false; +} + +static inline bool __rtld_tbg_has_triggered(const uint32_t index) +{ + if (!__rtld_tbg_triggered) + __rtld_tbg_triggered = + (__rtld_trace_triggers[index / 32] & (1 << (index & (32 - 1)))) != 0 ? true : false; + return __rtld_tbg_triggered; +} + +static inline uint8_t* __rtld_tbg_buffer_alloc(const uint32_t index, const uint32_t size) +{ + uint8_t* in = NULL; + if (!__rtld_tbg_finished && __rtld_tbg_has_triggered(index) && __rtld_tbg_is_enabled(index)) + { + const uint32_t slots = ((size - 1) / sizeof(uint32_t)) + 1; + if (__rtld_tbg_buffer_in >= ((RTLD_TRACE_BUFFER_WORDS - slots))) + { + __rtld_tbg_finished = true; + } + else + { + in = (uint8_t*) &__rtld_tbg_buffer[__rtld_tbg_buffer_in]; + __rtld_tbg_buffer_in += slots; + } + } + return in; +} + +static inline void __rtld_tbg_buffer_entry(uint8_t** in, uint32_t func_index, uint32_t size) +{ + if (*in) + { + uint32_t* in32 = (uint32_t*) *in; + uint64_t now = rtems_clock_get_uptime_nanoseconds(); + *in32++ = func_index | (size << 16) | __rtld_tbg_in_irq(); + *in32++ = __rtld_tbg_executing_id(); + *in32++ = __rtld_tbg_executing_status(); + *in32++ = __rtld_tbg_executing_state(); + *in32++ = now >> 32; + *in32 = now; + *in += sizeof(func_index) + (3 * sizeof(uint32_t)) + sizeof(uint64_t); + } +} + +static inline void __rtld_tbg_buffer_arg(uint8_t** in, int arg_size, void* arg) +{ + if (*in) + { + memcpy(*in, arg, arg_size); + *in += arg_size; + } +} + +static inline void __rtld_tbg_buffer_exit(uint8_t** in, uint32_t func_index, uint32_t size) +{ + if (*in) + { + uint32_t* in32 = (uint32_t*) *in; + uint64_t now = rtems_clock_get_uptime_nanoseconds(); + *in32++ = (1 << 30) | func_index | (size << 16) | __rtld_tbg_in_irq(); + *in32++ = __rtld_tbg_executing_id(); + *in32++ = __rtld_tbg_executing_status(); + *in32++ = __rtld_tbg_executing_state(); + *in32++ = now >> 32; + *in32 = now; + *in += sizeof(func_index) + (3 * sizeof(uint32_t)) + sizeof(uint64_t); + } +} + +static inline void __rtld_tbg_buffer_ret(uint8_t* in, int ret_size, void* ret) +{ + if (in) + { + memcpy(in, ret, ret_size); + } +} +CODE -- cgit v1.2.3