diff --git a/App/lib/core/Gen/DebugInfoGen.vp b/App/lib/core/Gen/DebugInfoGen.vp index fc300c4..1693fcc 100644 --- a/App/lib/core/Gen/DebugInfoGen.vp +++ b/App/lib/core/Gen/DebugInfoGen.vp @@ -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: