You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
reacted with thumbs up emoji reacted with thumbs down emoji reacted with laugh emoji reacted with hooray emoji reacted with confused emoji reacted with heart emoji reacted with rocket emoji reacted with eyes emoji
Uh oh!
There was an error while loading. Please reload this page.
工作日志
a. 白名单的获取依赖详细调试信息,需要能够获得函数返回值类型;
b. 调试器对 Riscv 架构的适配;
详细日志如下:
第一阶段:内核态异步追踪(coroutine_test)
1. 白名单中没有异步函数
排查过程
没有文件路径、行号、返回类型(-> core::task::poll::Poll<...>)。async-debug 的poll函数识别逻辑依赖返回类型,所以原因是:
release 模式编译的 ELF 缺少完整调试信息,GDB 的 info functions 输出不包含函数签名和返回类型,导致白名单生成器无法识别异步函数。
解决方案
在 release 编译时追加 -g 标志,嵌入调试信息但不改变代码优化:
make build ARCH=riscv64 BLK=n \ RUSTFLAGS="-C link-arg=-T/home/iristseng/data/async-os/linker_riscv64-qemu-virt.lds -C link-arg=-no-pie -C force-frame-pointers=yes -g"NOTE:
用了裸汇编直接写 JAL 跳转,debug 代码膨胀后编译无法通过。要修得改汇编,改动太大了。所以选择了上面的方案。
2. 影子栈始终为空
排查过程
断点能命中,但 snapshot 的
path始终是空数组[],面板没有节点产生。白名单没有问题,问题可能出在path 的产生环节,看了path的产生函数,path 是空的只可能两个原因:poll_sym 为空,或 this_ptr为零。
runtime_trace.py有一行:this_ptr = _reg_u64("rdi"),rdi 是 x86_64 寄存器,但是async-os是运行在riscv上的,问题大概出在这里。解决方案
添加架构检测函数,替换所有的硬编码。
成功获得了异步树
3. snapshot 中有重复 CID 节点
{"thread_id": 1, "path": [{"type": "async", "cid": 1, "func": "coroutine_test::keep_name::{async_block#0}", "addr": "-0x3f7fd54330", "poll": 0, "state": 5, "file": "apps/coroutine_test/src/main.rs", "fullname": "/home/iristseng/data/async-os/apps/coroutine_test/src/main.rs", "line": 12}, {"type": "async", "cid": 1, "func": "coroutine_test::keep_name::{async_block#0}", "addr": "-0x3f7fd54330", "poll": 0, "state": 5, "file": "apps/coroutine_test/src/main.rs", "fullname": "/home/iristseng/data/async-os/apps/coroutine_test/src/main.rs", "line": 12}]}同一个 CID=1 的节点在 path 中出现了两次,poll 计数也相同。这也导致异步树中有重复节点。
具体原因不是很清楚,之前path中运行完的poll函数会依靠GDB的gdb.FinishBreakpoint识别poll函数的出口然后弹出path中的节点,可能是哪个环节出错了,导致断点出口没识别到,所以我尝试在path添加时增加一个判断:
这个poll函数之前有没有被设置过CID,还在不在path中,如果在则将它清除。因为一个poll函数要是没有运行完,是不会被再次poll的。
4. gdb.FinishBreakpoint 在 RISC-V 上不工作
根据上面那个问题,我进行了相应的修改,但是发现发现 poll 值始终为 0。根据PollEntryBP中的实现,由于poll的值一直都不增加,分析PollEntryBP的实现,所以大概率是PopOnReturnBP(tid, cid)失败了,可能是这个GDB和Riscv适配的不是很好?不知道。
写最小测试验证:
结果:
确认是 gdb.FinishBreakpoint的问题了,这也解释了上一个问题。在上一个问题的解决基础上去掉_PopOnReturnBP的异常,保护后续逻辑。
第二阶段:跨特权级调试(user_boot)
经过前面的步骤,async-os的内核异步函数可以追踪到了,接下来就是尝试特权级切换的异步跟踪。
需要编译用户态的程序,指令如下:
make build A=apps/user_boot ARCH=riscv64 MODE=release \ RUSTFLAGS="-C link-arg=-T/home/iristseng/data/async-os/linker_riscv64-qemu-virt.lds -C link-arg=-no-pie -C force-frame-pointers=yes -g"5. Border 断点只支持 file:line 匹配,不支持函数名
async-debug中的os调试还未加入函数名匹配的功能,并且async-os和StarryOS一样,边界断点的源代码并没有在工作区,所以只能通过函数名设置断点。把这个功能移植过来就好(从osgdb)
8. Hook breakpoint 只有函数名时崩溃
启动时hook断点报错,
命令 "ARD: Set Hook Breakpoints from launch.json" 导致错误 Cannot read properties of undefined (reading 'replace')原因是因为调试器要求hook断点有
breakpoint.file和breakpoint.line,我上一步对hook断点也实现了函数名确定的方法(无文件名和行号),但是没改全,导致报错。9.
user_boot启动后直接退出,断点不命中QEMU 终端输出如下,输出完
[ 0.000000 0 vsched2::api:63] kernel_init_main complete!就退出了:查看调试控制台,发现应该是缺少磁盘镜像,最开始我尝试编译了用户态程序,会自动生成磁盘镜像,但是经检查,应该是之前编译用户态程序的时候报错了,没注意到,尝试重新编译。(缺少一些依赖)
All reactions