使kgtp支持存储超过一页的内存数据
这周完成了中期计划,这个是commit:https://code.csdn.net/lynuszhu/gktp/commit/057f9cc901346a42e7d45e41031fb046453b722f
1. kgtp的Ring Buffer模型
目前的焦点是在gtp_rb.c文件中实现的ringbuffer模型。
核心数据结构:
struct gtp_rb_s {
spinlock_t lock;
/* Pointer to the prev frame entry head.
*/
void *prev_frame;
/* When write, this is the next address to be write.
When read, this is the end of read. */
void *w;
/* When alloc memory from rb, record prev value W to PREV_W.
When this memory doesn't need, set W back to PREV_W to release
this memroy. */
void *prev_w;
/* Point to the begin of ring buffer. Read will begin from R. */
void *r;
/* Point to the trace frame entry head of current read. */
void *rp;
/* This the id of rp point to.
0 means rp doesn't point to a trace frame entry.
So it need call gtp_rb_walk first. */
u64 rp_id;
/* The cpu id. */
int cpu;
};
ringbuffer示意图:
ringbuffer并不保证使用连续内存,它使用类似链表形式将一块块内存page串联到一起,每页内存的前sizeof(size_t)字节和最后sizeof(size_t)字节分别是上一页和下一页的地址。
gdb的frame与kgtp的frame在ringbuffer中的示意图:
gdb的一个frame是指当hit tp时,kgtp根据用户在当前tp定义的所有action所收集的所有数据(内存数据,寄存器,TSV)保存在的一块连续区域。首先会在ringbuffer内分配一块head_frame,在内部保存了触发中断的tp编号,和一个新生成的id号;接下来执行各个具体action,例如执行memory_read(addr,size)操作,首先申请从ringbuffer申请一块内存,在内存首部打上记号FID_MEM意为当前frame保存了内存数据;接下来是地址addr和长度size,最后是内存数据正文。因为每次中断时候会把所有action一起执行完,所以每个head_frame后面跟着的frame都是由同一次tp的触发产生的。所以gdb用户所看到的frame是由head_frame引领的一串action frame.
目前的实现不支持一个action frame 跨页保存,导致的问题有1.当前页分配不了申请的数据块长度,只有废弃当前页,跳到下一页去分配 2.若申请长度在一块全新页也无法分配,则报错退出。这就引出了这次CSDN开源活动要解决的主要问题。
要解决这个问题,简单的方法是1.将一个大的内存切片,分为多个frame保存。2.在gtp_gdbrsp_m函数中支持从多个frame中读取还原原来大的数据块。幸运的是,第二步原来的代码已经支持了:
while (1) {
struct gtp_frame_mem *mr;
ULONGEST cur_start, cur_end;
uint8_t *buf;
tmp = gtp_rb_walk(&rbws, tmp);
if (rbws.reason != gtp_rb_walk_type)
break;
mr = (struct gtp_frame_mem *) (tmp + FID_SIZE);
buf = tmp + GTP_FRAME_MEM_SIZE;
cur_start = max(((ULONGEST)mr->addr), addr);
cur_end = min(((ULONGEST)mr->addr
+ mr->size),
(addr + len));
if (cur_start < cur_end) {
memcpy(gtp_m_buffer + cur_start - addr,
buf + cur_start - mr->addr,
cur_end - cur_start);
ret = 0;
}
tmp += FRAME_ALIGN(GTP_FRAME_MEM_SIZE
+ mr->size);
}
所以我要做的就是第一步。