Skip to content
New issue

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

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

Already on GitHub? Sign in 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 · 7 comments
Open
4 tasks done

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

kmARC opened this issue Aug 14, 2024 · 7 comments

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?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants