fix(dwarf): DIFile 改用绝对路径,栈转储显示完整路径并回读源码行
根因:CurrentFile 是项目相对路径(./Test/LLvmLiteTest/App/main.vp),LLVM 把该目录写成 CU 的 DW_AT_comp_dir,主文件条目用 dir_index: 0 指向 comp_dir;stackmap 写入端只解析 --debug-line(无 comp_dir)⇒ 行记录退化成裸名 main.vp,运行期既显示不全也无法按路径重读源码行 改法:DIFile filename 保留整条绝对路径(相对路径先经 w32file.GetCurrentDirectoryA 前置 CWD,与 Repl.vp 同款低层调用,不经 os._mbuddy);directory 另存目录前缀。无论 LLVM 保留整条 name 还是拆成 dir+basename,写端都得到绝对路径,故无需改写入端
This commit is contained in:
1 parent
bb864dff6f
commit
a79e723e8d
1 file changed
+34
-6
@@ -5,6 +5,7 @@ import memhub
|
||||
import string
|
||||
import stdlib
|
||||
import viperlib
|
||||
import w32.win32file as w32file
|
||||
import lib.core.VLogger as VLogger
|
||||
|
||||
# ============================================================
|
||||
@@ -156,29 +157,56 @@ def _EnsureModuleNodes(pool: memhub.MemBuddy*) -> int:
|
||||
mod: llvmlite.LLVMModule* = _g_mod
|
||||
if mod is None:
|
||||
return 1
|
||||
# DIFile: basename + absolute directory, backslashes normalised to '/'
|
||||
# DIFile: **绝对**路径(正斜杠),filename 保留整条路径。
|
||||
# 为什么必须绝对:本工程给 CurrentFile 的是**项目相对**路径(如
|
||||
# "./Test/LLvmLiteTest/App/main.vp"),LLVM 会把该目录写成 CU 的 DW_AT_comp_dir,
|
||||
# 而主文件条目用 `dir_index: 0` 指向 comp_dir;stackmap 写入端只解析
|
||||
# `llvm-dwarfdump --debug-line`(其中**没有** comp_dir)⇒ 行记录只能退化成裸文件名
|
||||
# "main.vp":运行期既显示不全,也无法按路径重读源码行(实证:曾整段栈都打印
|
||||
# `File "main.vp", line N` 而无源码行)。
|
||||
# 绝对化后,无论 LLVM 保留整条 name(写入端 `_tb_is_abs_path` 命中 ⇒ 原样采用)
|
||||
# 还是把它拆成 dir+basename(dir_index 指向同一个绝对目录 ⇒ 拼回绝对路径),
|
||||
# 结果都是绝对路径 —— 故本改动不需要动写入端。
|
||||
src: str = _g_file_path
|
||||
if src is None:
|
||||
src = ""
|
||||
slen: sizet = string.strlen(src)
|
||||
nbuf: str = pool.alloc(slen + 4)
|
||||
cap_n: sizet = slen + 4112
|
||||
nbuf: str = pool.alloc(cap_n)
|
||||
if nbuf is None:
|
||||
VLogger.error("--traceback: DIFile 路径缓冲分配失败,终止编译", "DWARF")
|
||||
return 1
|
||||
if slen > 0:
|
||||
string.strncpy(nbuf, src, slen)
|
||||
nbuf[slen] = '\0'
|
||||
if slen > 0 and nbuf[0] != '/' and not (slen >= 2 and nbuf[1] == ':'):
|
||||
# 相对路径 → 前置当前工作目录。用 w32file 低层调用(同 Repl.vp),
|
||||
# 不经 os._mbuddy:编译器进程未必初始化过那个内存管理器。
|
||||
CwdBuf: bytes = pool.alloc(4112)
|
||||
if CwdBuf is not None:
|
||||
CwdBuf[0] = '\0'
|
||||
nc: ULONG = w32file.GetCurrentDirectoryA(ULONG(4111), CwdBuf)
|
||||
if nc > 0:
|
||||
# 防御:缓冲区不足时 GetCurrentDirectoryA 的写入内容未定义,强制补 NUL
|
||||
CwdBuf[4110] = '\0'
|
||||
viperlib.snprintf(nbuf, cap_n, "%s/%s", CwdBuf, src)
|
||||
# 归一所有反斜杠(CWD 段同样可能含 '\')
|
||||
flen: sizet = string.strlen(nbuf)
|
||||
ni: sizet = 0
|
||||
for ni in range(slen):
|
||||
for ni in range(flen):
|
||||
if nbuf[ni] == '\\':
|
||||
nbuf[ni] = '/'
|
||||
# filename 取整条路径;directory 另存其目录前缀(两段各自 NUL 结尾,互不污染)
|
||||
fname: str = nbuf
|
||||
directory: str = ""
|
||||
slash: str = string.strrchr(nbuf, '/')
|
||||
if slash is not None:
|
||||
fname = slash + 1
|
||||
slash[0] = '\0'
|
||||
directory = nbuf
|
||||
dlen: sizet = string.strlen(nbuf) - string.strlen(slash + 1) - 1
|
||||
dirbuf: str = pool.alloc(dlen + 1)
|
||||
if dirbuf is not None:
|
||||
string.strncpy(dirbuf, nbuf, dlen)
|
||||
dirbuf[dlen] = '\0'
|
||||
directory = dirbuf
|
||||
dsize: sizet = string.strlen(fname) + string.strlen(directory) + 96
|
||||
dbuf: str = pool.alloc(dsize)
|
||||
if dbuf is None:
|
||||
|
||||
Reference in new issue
Block a user