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.
工作内容
我重新按照OS调试逻辑链梳理了一下代码,找到了如下几个问题(attach → QEMU → GDB → 状态机 → 断点组切换):
问题 1:handleBreakpointHit 在 OS 模式下无条件发送 StoppedEvent
handleBreakpointHit 总是发送 StoppedEvent。但在 border 断点和 hook 断点命中时应该是透明的(不应暂停 UI),状态机应该自动 continue。
问题 2:doAction 中的异步操作与状态机的同步执行冲突
状态机在 kernel 状态收到 STOPPED 事件时,会产生两个 action:
a. try_get_next_breakpoint_group_name
b. check_if_kernel_to_user_border_yet
这两个 action 都是异步的(内部用 .then()),但 forEach 是同步遍历的。这意味着:
这两个问题解决后,我又写了一个test来测试状态机和doActive流程,没有问题,就开始尝试调试rCore,还是不行,我就突然想到一个问题:
为什么我还没启动插件,但是vscode的右上角会有插件的按钮,这应该是不对的吧,我意识到自己之前设置边界断点和hook都是用这个按钮设置的,这个按钮是我之前安装code-debug的插件面板,和我现在开发的这个async-debug没有相关性,所以设置断点不应该用那两个按钮,看了一下,最后清楚了。当前这个插件ardb 设置hook断点和边界断点是通过vscode的命令面板设置的,所以我之前的两种重要断点设置都错了,更别说调试了。现在能够成功使用border和hook了。
问题:运行到用户态,调试器卡在单步判断,一直无法切换到用户态,但是用户态的initproc已经运行了一部分了。
解决:从内核到用户态的border设置的有问题,在launch.json改完后,就能够切换到initproc的断点组了。
问题:卡在了initproc中,怎么也到不了user_shell。
解决:这次的问题和之前是相同的,但不同的是调试控制台输出了很多信息,包括从user单步到内核的过程它都有在输出日志,通过日志分析,就发现了核心问题。**每次 trap_return 后切换的都是 initproc 而不是 user_shell。这说明 nextBreakpointGroup 没有被 sys_exec 的 hook 设置成 user_shell 的路径。**由于通知中没有没有出现 "hook matched, next group: ..." 的通知,意味着 hook 行为函数大概率执行失败了(被 try/catch 静默捕获了)。这个问题24年的时候也遇到过,所以去检查hook的行为函数。
由于hook当前报错会被吞掉,所以去掉 try/catch,让 hook 错误显式抛出来,能在调试控制台看到错误。(toFunctionString 总是生成 function(...),从来没考虑oisAsynci标志。你的 launch.json 里 behavior.isAsync: true,但代码完全忽略了这个字段,导致生成的是同步函数 function() { let p=await ...; },而 await 只能用在 async 函数里——所以语法错误。)

这个bug修复后,出现了第二个问题:
原因是 launch 中的配置使用了 this,但是它是 undefined,且getStringVariable 这个 API 目前还没实现,移植的时候漏掉了。这个参考code-debug的实现方式直接搬过来就好了。
然后hook有出现了第三个问题:
原因是 GDB 在执行 x /s path 时报错,在 process.rs hook断点处中 path 已经不是裸指针了(前面的代码已经把它翻译成 Rust String 了),GDB 没法对一个 Rust String 用 x /s 来打印,所以我将hook断点前移了从49行移到了45行。
hook 成功运行了,但是没有解析出东西:
于是我直接在GDB的调试控制台中查询了如下内容:
可以知道,0x13048 根本读不到,hook 命中在 sys_exec 的入口,此时 path 类型是 *const u8(或 *mut u8),且 0x13048 是用户态虚拟地址。当前 CPU 用的是内核页表,这个地址映射不到,所以 GDB 读不到、x /s 失败、getStringVariable 自然返空。
需要先了解实际数据的情况,通过测试清楚了:
这是最终准备落地的 getStringVariable:
这个实现绑定 Rust String 内部布局(.vec.buf.ptr.pointer.pointer + .vec.len)。如果以后 rustc 改了字段路径就失效。成功了:
经过测试现在OS调试功能移植已经告一段落!
to do:
会议内容
All reactions