From 11986f94c032db78738eaace55079ed075435f08 Mon Sep 17 00:00:00 2001 From: Andreas Ragnerstam Date: Mon, 9 Nov 2026 16:03:49 +0100 Subject: [PATCH] Do not map breakpoint files to target= paths Breakpoints set on source lines never resolved when Simics had a path map rule like add-pathmap-entry "target=/host" "/". Such rules map binaries that the Linux tracker finds in the target file system to host files. When we mapped the host path of a source file back, the rule gave a file name like target=/host/path/to/.../code.c. The debug information never has that prefix, so the agent found no code. Skip rules with a "target=" source when we map host paths for breakpoints. Mapping from debug information to host paths is not changed. Signed-off-by: Andreas Ragnerstam --- CHANGELOG.md | 4 ++++ src/pathMapper.ts | 14 ++++++++++++++ src/test/pathMapper.test.ts | 15 +++++++++++++++ 3 files changed, 33 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 248034e..719bf07 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,6 +12,10 @@ All notable changes to the Simics Target Debug extension will be documented here ### Fixed +- Source breakpoints no longer get a `target=` prefix on their file name + when the agent has a path map rule for the target file system, such as + `add-pathmap-entry "target=/host" ...` for binaries found by the Linux + tracker. Such breakpoints never resolved. - The file pickers for symbol files now offer the standard file dialog, a `..` entry, and pick files in the current folder ([#29](https://github.com/intel/simics-vs-code-tcf-debug/issues/29)). diff --git a/src/pathMapper.ts b/src/pathMapper.ts index 02e6f51..06a1769 100644 --- a/src/pathMapper.ts +++ b/src/pathMapper.ts @@ -169,6 +169,10 @@ export class PathMapper { * Rules the agent got elsewhere, for example from the Simics command * add-pathmap-entry, are not used by the agent for breakpoints, so those * are applied in reverse here. + * + * Rules with a "target=" source are skipped. The Simics agent uses that + * prefix for files in the target's file system, such as binaries found + * by the OS awareness tracker, never for paths in the debug information. */ async toTarget(hostPath: string, contextId?: string): Promise { return (await this.toTargetLocation(hostPath, contextId)).path; @@ -176,6 +180,9 @@ export class PathMapper { async toTargetLocation(hostPath: string, contextId?: string): Promise { for (const r of this.rules) { + if (isTargetFileSystemPath(r.source)) { + continue; + } const p = mapPrefix(hostPath, r.destination, r.source); const query = pathMapContextQuery(r); if (p !== undefined && query && query !== "*" && query !== "**" && !contextId && !this.service) { @@ -202,6 +209,9 @@ export class PathMapper { } } for (const r of await this.otherAgentRules()) { + if (isTargetFileSystemPath(r.Source!)) { + continue; + } const p = mapPrefix(hostPath, r.Destination!, r.Source!); if (p !== undefined && (await this.matches(r.ContextQuery, contextId))) { return { @@ -400,6 +410,10 @@ export function mapPrefix(file: string, from: string, to: string): string | unde return `${to.replace(/[\\/]+$/, "")}${rest}`; } +function isTargetFileSystemPath(file: string): boolean { + return file.startsWith("target="); +} + function fileExists(file: string): boolean { try { return fs.statSync(file).isFile(); diff --git a/src/test/pathMapper.test.ts b/src/test/pathMapper.test.ts index 2c6cb5a..1eea2f8 100644 --- a/src/test/pathMapper.test.ts +++ b/src/test/pathMapper.test.ts @@ -273,6 +273,21 @@ test("toTarget maps agent rules for this host in reverse", async () => { } }); +// Rules like add-pathmap-entry "target=/host" "/" map binaries the tracker +// reports in the target's file system. Source paths must not get the +// "target=" prefix, the debug information never contains it. +test("toTarget does not reverse rules for the target file system", async () => { + const fake = fakePathMapService([ + { Source: "target=/host/disk3", Destination: "/disk3" }, + { Source: "/build", Destination: "/disk3/ws" }, + ]); + const agent = new PathMapper([], fake.service); + assert.equal(await agent.toTarget("/disk3/src/a.c"), "/disk3/src/a.c"); + assert.equal(await agent.toTarget("/disk3/ws/a.c"), "/build/a.c"); + const local = new PathMapper([{ source: "target=/host/disk3", destination: "/disk3" }], undefined); + assert.equal(await local.toTarget("/disk3/src/a.c"), "/disk3/src/a.c"); +}); + // PathMap.get also returns our own rules. They must not be used as agent // rules, since the agent already applies them. test("toTarget skips the rules this client sent itself", async () => {