gdbstub: add RLE compression

Refer to
https://sourceware.org/gdb/current/onlinedocs/gdb.html/Overview.html

w/o compression, nxgcore command took 41seconds.
w compression, 28second.

If we enable `set trust-readonly-sections on` to read from elf whenever
possible, it furture reduces to 14.9seconds.

Signed-off-by: xuxingliang <xuxingliang@xiaomi.com>
This commit is contained in:
xuxingliang 2024-09-24 17:49:30 +08:00 committed by Xiang Xiao
parent 81d704cd82
commit 89f3ef4480

View file

@ -122,6 +122,7 @@ static ssize_t gdb_hex2bin(FAR void *buf, size_t buf_len,
FAR const void *data, size_t data_len);
static ssize_t gdb_bin2bin(FAR void *buf, size_t buf_len,
FAR const void *data, size_t data_len);
static size_t gdb_encode_rle(FAR void *data, size_t data_len);
/* Packet creation helpers */
@ -350,6 +351,8 @@ static int gdb_send_packet(FAR struct gdb_state_s *state)
}
#endif
state->pkt_len = gdb_encode_rle(state->pkt_buf, state->pkt_len);
/* Send packet data */
ret = state->send(state->priv, state->pkt_buf, state->pkt_len);
@ -709,6 +712,102 @@ static ssize_t gdb_bin2bin(FAR void *buf, size_t buf_len,
return out_pos;
}
/****************************************************************************
* Name: gdb_count_repeat
*
* Description:
* Get how many bytes are repeated in coming data.
*
* Input Parameters:
* data - The buffer containing the encoded data.
* data_len - The length of the data to decode.
*
* Returned Value:
* The number of bytes repeated.
*
****************************************************************************/
static size_t gdb_count_repeat(FAR const char *data, size_t data_len)
{
char c = data[0];
size_t i = 1;
while (i < data_len && data[i] == c)
{
i++;
}
return i;
}
/****************************************************************************
* Name: gdb_encode_rle
*
* Description:
* Encode data in place using GDB RLE encoding.
*
* Input Parameters:
* data - The buffer containing the encoded data.
* data_len - The length of the data to decode.
*
* Returned Value:
* The number of bytes written to data on success.
*
****************************************************************************/
static size_t gdb_encode_rle(FAR void *data, size_t data_len)
{
static const int max_count = 127 - 29;
FAR char *buf = data;
size_t widx = 0;
size_t ridx = 0;
while (ridx < data_len)
{
size_t count = gdb_count_repeat(buf + ridx, data_len - ridx);
char c = buf[ridx];
ridx += count;
while (count >= max_count)
{
buf[widx++] = c;
buf[widx++] = '*';
buf[widx++] = max_count - 1 + 29;
count -= max_count;
}
if (count <= 3)
{
while (count > 0)
{
buf[widx++] = c;
count--;
}
continue;
}
buf[widx++] = c;
count--;
if (count + 29 == '$')
{
buf[widx++] = c;
buf[widx++] = c;
count -= 2;
}
else if (count + 29 == '#')
{
buf[widx++] = c;
count -= 1;
}
buf[widx++] = '*';
buf[widx++] = count + 29;
}
return widx;
}
/****************************************************************************
* Name: gdb_is_valid_region
* Description: