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
3 changes: 2 additions & 1 deletion Inc/generics.h
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ typedef int errcode;
#define C_CLR_LN CMD_ALERT "U"

/* The actual control codes that do the work */
#define CC_CLEAR_SCREEN "\033[2J\033[;H"
#define CC_CLEAR_SCREEN "\033[H\033[2J\033[3J"
#define CC_PREV_LN "\033[1F"
#define CC_CLR_LN "\033[K"
#define CC_COLOUR "\033[%d;3%dm"
Expand Down Expand Up @@ -99,6 +99,7 @@ char *genericsUnescape( char *str );
uint64_t genericsTimestampuS( void );
uint32_t genericsTimestampmS( void );
bool genericsSetReportLevel( enum verbLevel lset );
enum verbLevel genericsGetReportLevel( void );
void genericsFPrintf( FILE *stream, const char *fmt, ... );
char *genericsGetBaseDirectory( void );
const char *genericsBasename( const char *n );
Expand Down
2 changes: 1 addition & 1 deletion Inc/git_version_info.h.in
Original file line number Diff line number Diff line change
@@ -1 +1 @@
#define GIT_DESCRIBE "@VCS_TAG@"
#define GIT_DESCRIBE "@GIT_DESCRIBE@"
37 changes: 37 additions & 0 deletions Inc/rtos/exceptions.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
#ifndef EXCEPTIONS_H
#define EXCEPTIONS_H

#include <stdint.h>
#include <stdbool.h>

#define MAX_EXCEPTIONS (512)
#define NO_EXCEPTION (0xFFFFFFFF)

struct exceptionRecord {
uint64_t visits;
int64_t totalTime;
int64_t minTime;
int64_t maxTime;
int64_t entryTime;
int64_t maxWallTime;
int64_t thisTime;
int64_t stealTime;
uint32_t prev;
uint32_t maxDepth;
};

struct exceptionStats {
struct exceptionRecord er[MAX_EXCEPTIONS];
uint32_t exceptionActive;
int64_t timeStamp;
int64_t lastReportTicks;
};

const char* exceptionGetName(uint32_t exceptionNum);
void exceptionInit(struct exceptionStats *stats);
void exceptionEnter(struct exceptionStats *stats, uint32_t exceptionNum, int64_t timestamp);
void exceptionExit(struct exceptionStats *stats, int64_t timestamp);
void exceptionReset(struct exceptionStats *stats);
bool exceptionIsActive(struct exceptionStats *stats);

#endif
177 changes: 177 additions & 0 deletions Inc/rtos/rtos_support.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,177 @@
/* SPDX-License-Identifier: BSD-3-Clause */

/*
* RTOS Support for Orbuculum
* ==========================
*
* Generic RTOS thread tracking support
*/

#ifndef _RTOS_SUPPORT_H_
#define _RTOS_SUPPORT_H_

#include <stdint.h>
#include <stdbool.h>
#include "uthash.h"

/* RTOS Thread Entry */
struct rtosThread {
/* Thread identification */
uint32_t tcb_addr; /* Thread control block address (key) */
char name[64]; /* Thread name (from memory or "UNNAMED") */
uint32_t entry_func; /* Thread entry function address */
const char *entry_func_name; /* Thread entry function name from symbols */
int8_t priority; /* Thread priority (signed for RTX5) */
uint32_t name_ptr; /* Puntero al nombre en memoria (debug) */

/* Execution time tracking */
uint64_t accumulated_time_us; /* Accumulated execution time in current window (microseconds) */
uint64_t accumulated_cycles; /* Accumulated CPU cycles in current window */
uint64_t last_scheduled_us; /* Timestamp when thread became active (microseconds) */
uint64_t context_switches; /* Total number of times scheduled (all time) */
uint64_t window_switches; /* Number of switches in current window */
uint32_t max_cpu_percent; /* Maximum CPU usage seen (in 0.001% units) */

/* Thread state tracking for reuse detection */
uint32_t name_hash; /* Hash of name for change detection */
uint32_t func_hash; /* Hash of function for change detection */

UT_hash_handle hh; /* Hash handle */
};

/* RTOS types */
enum rtosType {
RTOS_NONE = 0,
RTOS_RTX5,
RTOS_FREERTOS,
RTOS_THREADX,
RTOS_UNKNOWN
};

/* RTOS verification result codes */
enum rtosVerifyResult {
RTOS_VERIFY_SUCCESS = 0, /* Target matches ELF */
RTOS_VERIFY_NO_CONNECTION = 1, /* Cannot connect to target (telnet down) */
RTOS_VERIFY_MISMATCH = -1, /* Target does not match ELF */
RTOS_VERIFY_ERROR = -2 /* Other error */
};

/* Forward declarations */
struct rtosState;
struct rtosThread;
struct SymbolSet;
struct rtosDetection;

/* RTOS Operations - Virtual table for RTOS-specific operations */
struct rtosOps {
/* Read thread information from target memory */
int (*read_thread_info)(struct rtosState *rtos,
struct SymbolSet *symbols,
struct rtosThread *thread,
uint32_t tcb_addr);

/* Get priority name string */
const char* (*get_priority_name)(int8_t priority);

/* Detect RTOS from symbols */
bool (*detect)(struct SymbolSet *symbols, struct rtosDetection *result);

/* Initialize RTOS-specific data */
int (*init)(struct rtosState *rtos, struct SymbolSet *symbols);

/* Cleanup RTOS-specific data */
void (*cleanup)(struct rtosState *rtos);

/* Get thread state name */
const char* (*get_state_name)(uint8_t state);

/* Check if a thread is the idle thread (optional) */
bool (*is_idle_thread)(struct rtosThread *thread);

/* Verify RTOS version match between ELF and target (optional) */
int (*verify_target_match)(struct rtosState *rtos, struct SymbolSet *symbols);
};

/* RTOS State */
struct rtosState {
enum rtosType type; /* Type of RTOS detected */
bool enabled; /* Is RTOS tracking active? */
const char *name; /* RTOS name string */

/* Operations table */
const struct rtosOps *ops; /* RTOS-specific operations */

/* Current state */
uint32_t current_thread; /* Currently executing thread TCB */
uint64_t last_switch_time; /* Timestamp of last context switch (system time) */
uint32_t last_cyccnt; /* Last CYCCNT value (32-bit wrapping counter) */
uint64_t total_cycles; /* Total accumulated cycles (handles wrapping) */
uint32_t cpu_freq; /* CPU frequency in Hz for time calculations */

/* Thread tracking */
struct rtosThread *threads; /* Hash table of all threads */
uint32_t thread_count; /* Number of threads detected */
uint32_t max_cpu_usage; /* Maximum CPU usage seen (in 0.01% units) */

/* RTOS-specific private data */
void *priv; /* Private data for RTOS implementation */

/* Configuration */
int telnet_port; /* Telnet port for GDB connection */

/* Output configuration for real-time events */
void *output_config; /* Output handler for thread switches (OutputConfig*) */
};

/* RTOS detection result */
struct rtosDetection {
enum rtosType type;
const char *name;
uint32_t confidence; /* 0-100% confidence in detection */
const char *reason; /* Why this RTOS was detected */
};

/* Function declarations */

/* Main RTOS detection and initialization */
struct rtosState *rtosDetectAndInit(struct SymbolSet *symbols, const char *requested_type, int options_telnetPort, uint32_t cpu_freq);

/* Register RTOS implementations */
void rtosRegisterRTX5(void);
void rtosRegisterFreeRTOS(void);
void rtosRegisterThreadX(void);
void rtosFree(struct rtosState *rtos);

/* Thread name/function lookup from symbols */
const char *rtosLookupPointerAsString(struct SymbolSet *symbols, uint32_t ptr_value);
const char *rtosLookupPointerAsFunction(struct SymbolSet *symbols, uint32_t ptr_value);
bool rtosResolveThreadInfo(struct rtosThread *thread, struct SymbolSet *symbols,
uint32_t name_ptr, uint32_t func_ptr);


/* DWT handling */
void rtosHandleDWTMatch(struct rtosState *rtos, struct SymbolSet *symbols,
uint32_t comp_num, uint32_t address, uint32_t value, int options_telnetPort);

void rtosHandleDWTMatchWithTimestamp(struct rtosState *rtos, struct SymbolSet *symbols,
uint32_t comp_num, uint32_t address, uint32_t value,
uint64_t itm_timestamp, int options_telnetPort);

/* Output functions */
void rtosDumpThreadInfo(struct rtosState *rtos, FILE *f, uint64_t window_time_us, bool itm_overflow, const char *sort_order);

/* Thread metrics update functions */
void rtosUpdateThreadCpuMetrics(struct rtosState *rtos, uint64_t window_time_us);
void rtosResetThreadCounters(struct rtosState *rtos);

/* Memory reading functions (implemented in orbtop_rtos.c) */
uint32_t rtosReadMemoryWord(uint32_t address);
char *rtosReadMemoryString(uint32_t address, char *buffer, size_t maxlen);

/* DWT configuration via telnet */
void rtosConfigureDWT(uint32_t watch_address);

/* Cache management */
void rtosClearMemoryCacheForTCB(uint32_t tcb_addr);

#endif /* _RTOS_SUPPORT_H_ */
119 changes: 119 additions & 0 deletions Inc/rtos/rtx5.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
/* SPDX-License-Identifier: BSD-3-Clause */

/*
* RTX5 Thread Tracking Support for Orbuculum
* ==========================================
* Host-side header for decoding RTX5 (CMSIS-RTOS2) data structures
* on a 32-bit ARMv7-M target (Cortex-M7). Keep ONLY target layout here.
*/

#ifndef _RTX5_H_
#define _RTX5_H_

#include <stdint.h>
#include <rtos_support.h>

/* --------------------------------------------------------------------------
* Target layout assumptions
* --------------------------------------------------------------------------
* - ARMv7-M (Cortex-M7) 32-bit
* - Little-endian
* - Natural alignment (no packed attributes in the target)
*
* All offsets below are ABSOLUTE from the symbol base of the corresponding
* target object (e.g., &osRtxInfo). Use them as 32-bit addresses; do NOT
* reinterpret with host pointer sizes.
*/

/* osRtxInfo (global RTOS runtime) — absolute offsets from &osRtxInfo */
#define RTX5_INFO_OS_ID_OFFSET 0x00u /* const char* */
#define RTX5_INFO_VERSION_OFFSET 0x04u /* uint32_t */
#define RTX5_INFO_KERNEL_OFFSET 0x08u /* struct {...} */
#define RTX5_INFO_TICK_IRQN_OFFSET 0x10u /* int32_t */

/* thread sub-structure (inside osRtxInfo) */
#define RTX5_INFO_THREAD_OFFSET 0x14u /* struct {...} */

/* thread.run sub-structure */
#define RTX5_INFO_THREAD_RUN_OFFSET 0x14u
#define RTX5_INFO_THREAD_RUN_CURR_OFFSET 0x14u /* osRtxInfo.thread.run.curr (osRtxThread_t*) */
#define RTX5_INFO_THREAD_RUN_NEXT_OFFSET 0x18u /* osRtxInfo.thread.run.next (osRtxThread_t*) */

/* Convenience macros (address arithmetic on 32-bit target addresses) */
#define RTX5_ADDR(base, off) ((uint32_t)((base) + (off)))
#define RTX5_ADDR_CURR(base) RTX5_ADDR((base), RTX5_INFO_THREAD_RUN_CURR_OFFSET)
#define RTX5_ADDR_NEXT(base) RTX5_ADDR((base), RTX5_INFO_THREAD_RUN_NEXT_OFFSET)

/* RTX5 Thread Control Block (TCB) — offsets from a thread control block base */
#define RTX5_THREAD_ID_OFFSET 0 /* uint8_t id (1=thread,2=timer,...) */
#define RTX5_THREAD_STATE_OFFSET 1 /* uint8_t state */
#define RTX5_THREAD_FLAGS_OFFSET 2 /* uint8_t flags */
#define RTX5_THREAD_ATTR_OFFSET 3 /* uint8_t attributes */
#define RTX5_THREAD_NAME_OFFSET 4 /* uint32_t pointer to name */
#define RTX5_THREAD_THREAD_NEXT_OFFSET 8 /* uint32_t next in thread list */
#define RTX5_THREAD_THREAD_PREV_OFFSET 12 /* uint32_t prev in thread list */
#define RTX5_THREAD_DELAY_NEXT_OFFSET 16 /* uint32_t next in delay list */
#define RTX5_THREAD_DELAY_PREV_OFFSET 20 /* uint32_t prev in delay list */
#define RTX5_THREAD_THREAD_JOIN_OFFSET 24 /* uint32_t waiting-to-join thread */
#define RTX5_THREAD_DELAY_OFFSET 28 /* uint32_t delay time */
#define RTX5_THREAD_PRIORITY_OFFSET 32 /* int8_t priority */
#define RTX5_THREAD_PRIORITY_BASE_OFFSET 33 /* int8_t base priority */
#define RTX5_THREAD_STACK_FRAME_OFFSET 34 /* uint8_t stack frame type */
#define RTX5_THREAD_FLAGS_OPTIONS_OFFSET 35 /* uint8_t flags options */
#define RTX5_THREAD_WAIT_FLAGS_OFFSET 36 /* uint32_t waiting flags */
#define RTX5_THREAD_THREAD_FLAGS_OFFSET 40 /* uint32_t thread flags */
#define RTX5_THREAD_MUTEX_LIST_OFFSET 44 /* uint32_t owned mutex list ptr */
#define RTX5_THREAD_STACK_MEM_OFFSET 48 /* uint32_t stack memory ptr */
#define RTX5_THREAD_STACK_SIZE_OFFSET 52 /* uint32_t stack size */
#define RTX5_THREAD_SP_OFFSET 56 /* uint32_t current SP */
#define RTX5_THREAD_THREAD_ADDR_OFFSET 60 /* uint32_t entry function address */
#define RTX5_THREAD_TZ_MEMORY_OFFSET 64 /* uint32_t TZ memory id */
#define RTX5_THREAD_TZ_MODULE_OFFSET 68 /* uint32_t TZ module id */
#define RTX5_THREAD_RESERVED_OFFSET 72 /* uint32_t reserved */
#define RTX5_THREAD_ZONE_OFFSET 76 /* uint32_t zone number */

#define RTX5_THREAD_CB_SIZE 80 /* total size of TCB in bytes */

/* Thread states */
#define RTX5_THREAD_INACTIVE 0
#define RTX5_THREAD_READY 1
#define RTX5_THREAD_RUNNING 2
#define RTX5_THREAD_BLOCKED 3
#define RTX5_THREAD_TERMINATED 4

/* Object identifiers */
#define RTX5_ID_INVALID 0x00u
#define RTX5_ID_THREAD 0xF1u
#define RTX5_ID_TIMER 0xF2u
#define RTX5_ID_EVENTFLAGS 0xF3u
#define RTX5_ID_MUTEX 0xF5u
#define RTX5_ID_SEMAPHORE 0xF6u
#define RTX5_ID_MEMPOOL 0xF7u
#define RTX5_ID_MESSAGE 0xF9u
#define RTX5_ID_MESSAGEQUEUE 0xFAu

struct rtx5_info {
uint32_t thread_run_curr; /* current thread pointer (target address) */
uint32_t thread_run_next; /* next thread pointer (target address) */
};

struct rtx5_thread_track {
uint32_t thread_addr; /* TCB base address on target */
char name[64]; /* copied name */
uint32_t thread_func; /* entry function */
uint8_t priority; /* priority */
uint8_t state; /* state */
uint64_t total_cycles; /* stats */
uint64_t run_count;
uint64_t last_scheduled;
uint64_t min_runtime;
uint64_t max_runtime;
uint32_t stack_usage;
struct rtx5_thread_track *next;
struct rtx5_thread_track *prev;
};


const char *rtx5GetPriorityName(int8_t priority);
const struct rtosOps *rtx5GetOps(void);
#endif /* _RTX5_H_ */
Loading