Skip to content
New issue

Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? # to your account

GDB 12.1: -var-create: unable to create variable object #437

Open
4 tasks done
kmARC opened this issue Aug 14, 2024 · 8 comments · Fixed by #415
Open
4 tasks done

GDB 12.1: -var-create: unable to create variable object #437

kmARC opened this issue Aug 14, 2024 · 8 comments · Fixed by #415

Comments

@kmARC
Copy link

kmARC commented Aug 14, 2024

Symptom

When using a recent version of gdb (anything after 2022 March 08), the thread context is not selected by the extension anymore, and therefore (multi-threaded?) binaries cannot be properly debugged. Our team encountered two issues:

  • Debugging a multi-threaded binary resulted in never stopping at a breakpoint
  • -var-create: unable to create variable object error displayed next to variables when selecting a different stack frame from the Call stack list (see screenshot)
Screenshot 2024-08-14 at 11 17 11

Cause

I git-bisected the offending commit in gdb: bminor/binutils-gdb@a9c82bc changed how the thread / stack frame context is selected. From the commit message:

With this change, there are only two GDB/MI commands
that can change user selected context: -thread-select and -stack-select-frame.
This allows us to remove all and rather complicated logic of notifying
about user selected context change from mi_execute_command (), leaving it
to these two commands themselves to notify.

Workaround

  • Either after selecting the stack frame, manually invoke -stack-select-frame N with N being the stack frame number
  • Or apply the following patch on v0.27.0 of the extension
diff --git a/src/backend/mi2/mi2.ts b/src/backend/mi2/mi2.ts
index e641160..fcef83b 100644
--- a/src/backend/mi2/mi2.ts
+++ b/src/backend/mi2/mi2.ts
@@ -741,6 +741,7 @@ export class MI2 extends EventEmitter implements IBackend {
                if (trace)
                        this.log("stderr", "getStackVariables");

+               await this.sendCommand(`stack-select-frame ${frame}`);
                const result = await this.sendCommand(`stack-list-variables --thread ${thread} --frame ${frame} --simple-values`);
                const variables = result.result("variables");
                const ret: Variable[] = [];

Note that I'm not sure if this is the right spot to invoke -stack-select-frame. It seems to be performant and does its job.

System

  • If you are using gdb
    • gdb --version >= 12.1 (compiled from source, broken after bminor/binutils-gdb@a9c82bc)
    • it works on the command line with gdb (when invoking -stack-select-frame)
    • cwd and target are properly set

Other mentions

@GitMensch
Copy link
Collaborator

As that command is available in GDB since < 7.1 I think using it in some places may be the way to go - but that shouldn't be this place; checking the notes on the GDB change, this mostly means that no command should rely on a stack frame or thread to be set (it should be always explicit requested), as it previously was in this extension in some places.

@kmARC Starting from the message you see..
Can you please test the following change in the same file (backend/mi2/mi2.ts) instead (which, I guess, should fix the var-create issue):

 	async varCreate(threadId: number, frameLevel: number, expression: string, name: string = "-", frame: string = "@"): Promise<VariableObject> {
 		if (trace)
 			this.log("stderr", "varCreate");
-		let miCommand = "var-create ";
-		if (threadId != 0) {
-			miCommand += `--thread ${threadId} --frame ${frameLevel}`;
-		}
-		const res = await this.sendCommand(`${miCommand} ${this.quote(name)} ${frame} "${expression}"`);
+		cconst miCommand = `var-create --thread ${threadId} --frame ${frameLevel} ${this.quote(name)} ${frame} "${expression}"`;
+		const res = await this.sendCommand(`${miCommand}`);
 		return new VariableObject(res.result(""));
 	}

and do the the same change to evalExpression() and sendCliCommand()?

If this works out, then these changes, along with a Changelog entry, can be part of a PR.

@oltolm
Copy link
Contributor

oltolm commented Aug 21, 2024

I have already fixed it in be19c27.

@GitMensch
Copy link
Collaborator

I don't think so as you only pass the frame if there's a thread-id?!?
And even if the thread id is zero, I think we should always pass it, as it can be different in GDB (for example via console and commands executing at breakpoints) than in the ui, no?

@oltolm
Copy link
Contributor

oltolm commented Aug 21, 2024

I don't know if the thread id can even be zero in practice. The OP should just test the git version, but I don't know how to build the extension from source.

@kmARC
Copy link
Author

kmARC commented Aug 26, 2024

Thanks for looking into it!

Last week I couldn't build the master branch, therefore I was trying a fix on v0.27.0 (the latest tag that time).

I'm happy to report that today master succeeded to build and the issue is gone. I also tried removing the threadId check and it works with it too (the check for thread Id was changed by be19c27, so wasn't part of the last release yet, I think.)

@GitMensch
Copy link
Collaborator

GitMensch commented Aug 26, 2024 via email

@kmARC
Copy link
Author

kmARC commented Aug 26, 2024

So this PR should be closed?

As of now, this report is still valid; is there a new release scheduled any time soon?

@luckyfunky
Copy link

I also have this issue and would be happy about a new version :-)

@GitMensch GitMensch linked a pull request Nov 25, 2024 that will close this issue
# for free to join this conversation on GitHub. Already have an account? # to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

4 participants