This is an automated email from Gerrit. "Nguyen Huy Hoang <[email protected]>" just uploaded a new patch set to Gerrit, which you can find at https://review.openocd.org/c/openocd/+/9396
-- gerrit commit 17723a3c6e128cad160806b1d9aa7d9077f6f132 Author: hhoang308 <[email protected]> Date: Wed Jan 21 23:53:20 2026 +0700 target/rtt: support 64-bit targets by using dynamic offsets The current RTT implementation hardcodes the channel structure size to 24 bytes and uses fixed offsets for control block members. This conforms to the ILP32 (32-bit) layout but fails on LP64 (64-bit) targets such as RISC-V 64-bit or AArch64. On 64-bit targets: - Pointers are 8 bytes, increasing the channel struct size to 32 bytes. - Member offsets are shifted due to alignment. - Critically, the 'read_pos' offset moves from 0x10 (32-bit) to 0x18 (64-bit). The existing code writes to offset 0x10 to update the read position. On a 64-bit target, offset 0x10 corresponds to 'SizeOfBuffer'. This overwrites the buffer size with the read position value, causing memory corruption and immediate firmware crashes (boot loops). This patch introduces a dynamic parameter structure that selects the correct offsets and sizes at runtime based on 'target->address_bits'. It has been verified on a RISC-V 64-bit target running Zephyr RTOS. Change-Id: If839cb531042f4e6f135743462be932ac881ab4c Signed-off-by: hhoang308 <[email protected]> diff --git a/src/rtt/rtt.h b/src/rtt/rtt.h index d84fdb40b3..2f44450f2a 100644 --- a/src/rtt/rtt.h +++ b/src/rtt/rtt.h @@ -21,8 +21,11 @@ /* Control block size in bytes. */ #define RTT_CB_SIZE (RTT_CB_MAX_ID_LENGTH + 2 * sizeof(uint32_t)) -/* Channel structure size in bytes. */ -#define RTT_CHANNEL_SIZE 24 +/* Channel structure size in bytes (32-bit architecture). */ +#define RTT_CHANNEL_SIZE_32 24 + +/* Channel structure size in bytes (64-bit architecture). */ +#define RTT_CHANNEL_SIZE_64 32 /* Minimal channel buffer size in bytes. */ #define RTT_CHANNEL_BUFFER_MIN_SIZE 2 diff --git a/src/target/rtt.c b/src/target/rtt.c index a8ab24a60b..d1115a6407 100644 --- a/src/target/rtt.c +++ b/src/target/rtt.c @@ -18,32 +18,69 @@ #include "target.h" +/** Offsets for RTT control block parameters. */ +struct rtt_control_params { + uint32_t channel_size; + uint32_t buffer_addr_offset; + uint32_t size_offset; + uint32_t write_pos_offset; + uint32_t read_pos_offset; + uint32_t flags_offset; +}; + +/** Offsets for 32-bit architecture. */ +static const struct rtt_control_params rtt_params_32 = { + .channel_size = RTT_CHANNEL_SIZE_32, + .buffer_addr_offset = 4, + .size_offset = 8, + .write_pos_offset = 12, + .read_pos_offset = 16, + .flags_offset = 20 +}; + +/** Offsets for 64-bit architecture. */ +static const struct rtt_control_params rtt_params_64 = { + .channel_size = RTT_CHANNEL_SIZE_64, + .buffer_addr_offset = 8, + .size_offset = 16, + .write_pos_offset = 20, + .read_pos_offset = 24, + .flags_offset = 28 +}; + +static const struct rtt_control_params *get_rtt_params(struct target *target) +{ + if (target_address_bits(target) == 64) + return &rtt_params_64; + return &rtt_params_32; +} + static int read_rtt_channel(struct target *target, const struct rtt_control *ctrl, unsigned int channel_index, enum rtt_channel_type type, struct rtt_channel *channel) { int ret; - uint8_t buf[RTT_CHANNEL_SIZE]; + uint8_t buf[RTT_CHANNEL_SIZE_64]; target_addr_t address; + const struct rtt_control_params *params = get_rtt_params(target); - address = ctrl->address + RTT_CB_SIZE + (channel_index * RTT_CHANNEL_SIZE); + address = ctrl->address + RTT_CB_SIZE + (channel_index * params->channel_size); if (type == RTT_CHANNEL_TYPE_DOWN) - address += ctrl->num_up_channels * RTT_CHANNEL_SIZE; + address += ctrl->num_up_channels * params->channel_size; - ret = target_read_buffer(target, address, RTT_CHANNEL_SIZE, buf); + ret = target_read_buffer(target, address, params->channel_size, buf); if (ret != ERROR_OK) return ret; channel->address = address; channel->name_addr = target_buffer_get_u32(target, buf + 0); - channel->buffer_addr = target_buffer_get_u32(target, buf + 4); - channel->size = target_buffer_get_u32(target, buf + 8); - channel->write_pos = target_buffer_get_u32(target, buf + 12); - channel->read_pos = target_buffer_get_u32(target, buf + 16); - channel->flags = target_buffer_get_u32(target, buf + 20); - + channel->buffer_addr = target_buffer_get_u32(target, buf + params->buffer_addr_offset); + channel->size = target_buffer_get_u32(target, buf + params->size_offset); + channel->write_pos = target_buffer_get_u32(target, buf + params->write_pos_offset); + channel->read_pos = target_buffer_get_u32(target, buf + params->read_pos_offset); + channel->flags = target_buffer_get_u32(target, buf + params->flags_offset); return ERROR_OK; } @@ -93,6 +130,7 @@ static int write_to_channel(struct target *target, { int ret; uint32_t len; + const struct rtt_control_params *params = get_rtt_params(target); if (!*length) return ERROR_OK; @@ -157,7 +195,7 @@ static int write_to_channel(struct target *target, return ret; } - ret = target_write_u32(target, channel->address + 12, + ret = target_write_u32(target, channel->address + params->write_pos_offset, (channel->write_pos + len) % channel->size); if (ret != ERROR_OK) @@ -314,6 +352,7 @@ static int read_from_channel(struct target *target, { int ret; uint32_t len; + const struct rtt_control_params *params = get_rtt_params(target); if (!*length) return ERROR_OK; @@ -349,7 +388,7 @@ static int read_from_channel(struct target *target, } if (len > 0) { - ret = target_write_u32(target, channel->address + 16, + ret = target_write_u32(target, channel->address + params->read_pos_offset, (channel->read_pos + len) % channel->size); if (ret != ERROR_OK) --
