epasveer / seer

Seer - a gui frontend to gdb
GNU General Public License v3.0
2.11k stars 67 forks source link

[Question] - Connect to Qemu remote #100

Closed pathakraul closed 1 year ago

pathakraul commented 1 year ago

In my debugging setup, I usually run the riscv-qemu in debug mode and run the riscv-gdb and in that I just connect with that qemu instance via "target remote :1234"

With seer, I can see the option for gdbserver, but its always asking for the executable file name and path.

How can i use seer for my usecase?

Thanks

epasveer commented 1 year ago

Hi,

I'm not familiar with qemu, however, a question that might help me. Have you got some other GUI frontend to work for your use case? If so, which frontend? What things did you have to do for that?

run the riscv-gdb and in that I just connect with that qemu instance via "target remote :1234"

You don't have to give riscv-gdb the name of the executable?

pathakraul commented 1 year ago

Sorry for late reply, I was able to make seer work, just had to provide the path of qemu executable also along with gdb server port.

Qemu implements gdbstub which when spawned in gdb mode listens for the connection from gdb on the port 1234. https://qemu-project.gitlab.io/qemu/system/gdb.html

No executable name is required in this case. Normally simple applications dont implement gdb stub which require the executable name.

epasveer commented 1 year ago

The gdbstub/gdbserver is one area that I need to learn more of so I can improve seer. Thanks for the feedback. --ernie

On Thursday, October 6, 2022, 11:53:57 PM CDT, Rahul Pathak ***@***.***> wrote:  

Sorry for late reply, I was able to make seer work, just had to provide the path of qemu executable also along with gdb server port

Qemu implements gdbstub which when spawned in gdb mode listens for the connection from gdb on the port 1234. https://qemu-project.gitlab.io/qemu/system/gdb.html

No executable name is required in this case. Normally simple applications dont implement gdb stub which require the executable name.

— Reply to this email directly, view it on GitHub, or unsubscribe. You are receiving this because you commented.Message ID: @.***>

kevinferrare commented 1 year ago

Hi,

I just tried seer with an x86 emulator implementing gdbstub and I have the same issue. In the case of an emulator, client should connect to the gdb server and request relevant memory areas as the program executes. The initial executable being run is not that relevant for this use case anyways because other executable areas could be loaded and executed in emulated memory at runtime. For example compressed executables, or binaries loading other binaries from disk at runtime.

A front end that supports this use case with gdb is https://github.com/cyrus-and/gdb-dashboard but it's command line. I really hope I can switch to seer as it seems way easier to use :stuck_out_tongue_closed_eyes:

epasveer commented 1 year ago

Thanks for the feedback! I'll check gdb-dashboard out to see it's implemented.

epasveer commented 1 year ago

Boy, did I miss the boat on handling gdbserver. :^) I'm revamping the "connect" mode in Seer.

epasveer commented 1 year ago

If you pull that latest "v1.15beta", I've made a small change to the way Seer does "connect" to gdbserver.

It doesn't require the executable anymore. In fact, it checks that you don't provide one. It, optionally, will load a symbol file that can have the debug information that may not be available by the gdbserver's executable.

I have more to do...

kevinferrare commented 1 year ago

Thank you for your fix, It kind of works now!

However the window is not displaying the asm listing, not sure whether or not this is the expected behaviour

epasveer commented 1 year ago

Hi.

To confirm, have you enabled the assembly view with "View->AssemblyView"?

kevinferrare commented 1 year ago

I just tried now, and the Assembly area is empty. It displays fine with the memory visualizer though.

epasveer commented 1 year ago

Hmmm. I think I need to investigate Qemu some more. Also, I'll look further into gdb-dashboard.

Can you provide how you launch gdbserver (command line arguments) and how you launch Seer?

Thanks.

kevinferrare commented 1 year ago

Of course, but it's not qemu, it's Spice86: https://github.com/OpenRakis/Spice86/releases/tag/latest

Download the zip, extract it and run the Spice86 application like this:

./Spice86 --Exe /path/to/a/dos/exe/or/a/bios.bin --GdbPort=10000

You can use one of the bin here: https://github.com/OpenRakis/Spice86/tree/master/src/Spice86.Tests/Resources/cpuTests

The emulator will pause before executing the first instruction and listen on port 10000

In seer I just fill the gdbserver field: image

With the official command line gdb client I just run the gdb command with a .gdbinit file containing this:

target remote localhost:10000
set architecture i8086
epasveer commented 1 year ago

Perfect! I'll give it a try.

Thanks!

epasveer commented 1 year ago

I grabbed the Spice86 release. Trying the linux-x64 binary. Crashes in "Ice", which I don't know what is.

erniep@gracie:/nas/erniep/Development/spice86/Release/net7.0/linux-x64$ gdb ./Spice86 
Reading symbols from ./Spice86...
(No debugging symbols found in ./Spice86)
(gdb) run --Exe ./div.bin --GdbPort=2222
Starting program: /nas/erniep/Development/spice86/Release/net7.0/linux-x64/Spice86 --Exe ./div.bin --GdbPort=2222
Thread 1 "Spice86" received signal SIGSEGV, Segmentation fault.
0x00007fbf5310c0ca in _IceConnectionOpened () from /usr/lib64/libICE.so.6
(gdb) where
#0  0x00007fbf5310c0ca in _IceConnectionOpened () from /usr/lib64/libICE.so.6
#1  0x00007fbf530ffb05 in IceOpenConnection () from /usr/lib64/libICE.so.6
#2  0x00007fbf52ef3044 in SmcOpenConnection () from /usr/lib64/libSM.so.6
#3  0x00005554d72f829a in ?? ()
#4  0x0000000000000000 in ?? ()
(gdb) 
maximilien-noal commented 1 year ago

Hi,

That's strange ! I'm on Fedora Workstation 37, and it runs fine. Never tested with an other port than 10000, however.

I made a Debug build, so it would hopefully give more errors : https://github.com/OpenRakis/Spice86/releases

epasveer commented 1 year ago

Thanks. I'll try the debug build.

I ran it on OpenSuse 15.4. I have a Debian box with the latest Debian. I'll try it there too.

What is ICE? And what is it used for?

Thanks.

maximilien-noal commented 1 year ago

What is ICE? And what is it used for?

I dunno. Probably a low-level dependency that the dotnet runtime requires.

Here is the list of supported distributions:

Alpine

CentOS

Debian

Fedora

openSUSE

SLES

Ubuntu

Sorry about this inconvenience.

epasveer commented 1 year ago

Never tested with an other port than 10000, however. I tried with 10000, then with 2222.

I'll let you know how my Debian box gets along.

kevinferrare commented 1 year ago

For information, libICE seems to be a low level X11 lib: https://www.x.org/releases/X11R7.7/doc/libICE/ICElib.html It is indeed odd that the program is crashing at this level.

maximilien-noal commented 1 year ago

@epasveer any update on this, pretty please ? :)

kevinferrare commented 1 year ago

I just checked with latest commits:

epasveer commented 1 year ago

Hi Kevin,

however there is still no disassembly in the main window

Very strange.

I've added a debug to the latest snapshot. Can you do these things to help me debug the problem?

1/ First, launch Seer and enable the output in the Seer Output tab. Then quit Seer. Seer will remember this for the next time.

image

2/ Then run your debugging session as you normally do. However add the "-xxx" flag. This will print lots of debug info to stdout. You'll need to redirect it to a file. Also, debug info will be sent to the above Seer Output tab. There is a button to save the contents of the Seer Ouput tab to a file.

$ seergdb -xxx -s hellosegv > seer.log 2>&1

If you could, please attach both log files to this task.

Note, debug won't print until you ask for the Assembly tab to show.

image

kevinferrare commented 1 year ago

Thanks for the reply! I activated the gdb output and did almost as you suggested. I had to remove the -s option because it was making seer crash with: "hellosegv: No such file or directory."

Even when the assembly view is selected in the menu, the main window is showing nothing.

Also I noticed the connection is taking a lot of time whereas with the command line client this is instantaneous. Is there a way to see the commands seer is sending to the server?

Here are some logs where I connect and enable assembly view (which was blank): seer.log:

[14:48:10][unknown:0][default] Starting GdbConnect.
[14:48:10][unknown:0][default] Finishing GdbConnect.
[14:48:24][unknown:0][default] "^connected"
[14:48:30][unknown:0][default] "^done,stack=[frame={level=\"0\",addr=\"0x0001080e\",func=\"??\",arch=\"i8086\"}]"
[14:48:30][unknown:0][default] "4^done,value=\"0x1080e\""
[14:48:30][unknown:0][default] "5^done,value=\"0x80\""
[14:48:30][unknown:0][default] "6^done,value=\"[ IF NT ]\""

gdboutput.log:

=thread-group-added,id="i1"
=cmd-param-changed,param="architecture",value="i8086"
^done
^done
^done
=thread-group-started,id="i1",pid="42000"
=thread-created,id="1",group-id="i1"
*stopped,frame={addr="0x0001080e",func="??",args=[],arch="i8086"},thread-id="1",stopped-threads="all"
^connected
^done
^done,files=[]
^done
^done
^done
^done
^done,BreakpointTable={nr_rows="0",nr_cols="6",hdr=[{width="7",alignment="-1",col_name="number",colhdr="Num"},{width="14",alignment="-1",col_name="type",colhdr="Type"},{width="4",alignment="-1",col_name="disp",colhdr="Disp"},{width="3",alignment="-1",col_name="enabled",colhdr="Enb"},{width="10",alignment="-1",col_name="addr",colhdr="Address"},{width="40",alignment="2",col_name="what",colhdr="What"}],body=[]}
^done,BreakpointTable={nr_rows="0",nr_cols="6",hdr=[{width="7",alignment="-1",col_name="number",colhdr="Num"},{width="14",alignment="-1",col_name="type",colhdr="Type"},{width="4",alignment="-1",col_name="disp",colhdr="Disp"},{width="3",alignment="-1",col_name="enabled",colhdr="Enb"},{width="10",alignment="-1",col_name="addr",colhdr="Address"},{width="40",alignment="2",col_name="what",colhdr="What"}],body=[]}
^done,BreakpointTable={nr_rows="0",nr_cols="6",hdr=[{width="7",alignment="-1",col_name="number",colhdr="Num"},{width="14",alignment="-1",col_name="type",colhdr="Type"},{width="4",alignment="-1",col_name="disp",colhdr="Disp"},{width="3",alignment="-1",col_name="enabled",colhdr="Enb"},{width="10",alignment="-1",col_name="addr",colhdr="Address"},{width="40",alignment="2",col_name="what",colhdr="What"}],body=[]}
^done,thread-ids={thread-id="1"},current-thread-id="1",number-of-threads="1"
^done,threads=[{id="1",target-id="Thread 1",details="spice86
",frame={level="0",addr="0x0001080e",func="??",args=[],arch="i8086"},state="stopped"}],current-thread-id="1"
^done,stack=[frame={level="0",addr="0x0001080e",func="??",arch="i8086"}]
^done,thread-ids={thread-id="1"},current-thread-id="1",number-of-threads="1"
^done,threads=[{id="1",target-id="Thread 1",details="spice86
",frame={level="0",addr="0x0001080e",func="??",args=[],arch="i8086"},state="stopped"}],current-thread-id="1"
^done,threads=[{id="1",target-id="Thread 1",details="spice86
",frame={level="0",addr="0x0001080e",func="??",args=[],arch="i8086"},state="stopped"}],current-thread-id="1"
^error,msg="-data-disassemble: No function contains specified address"
^done,stack=[frame={level="0",addr="0x0001080e",func="??",arch="i8086"}]
4^done,value="0x1080e"
5^done,value="0x80"
6^done,value="[ IF NT ]"
epasveer commented 1 year ago

Hi Kevin. Thanks for the debug logs.

I see this message, which tells me the assembly view will not be populated.

^error,msg="-data-disassemble: No function contains specified address"

The function it complains of comes from the stack frame. Which has "??" as the name of the function.

^done,stack=[frame={level="0",addr="0x0001080e",func="??",arch="i8086"}]

I doubt the debugging information in your executable has any function called "??". It's likely Seer is not handling this use case. I do see it has an address of "0x0001080e". So I think I can use that if FUNC equals "??". Let me work on this.

I suspect your program might be pure assembly?

kevinferrare commented 1 year ago

Hi Ernie, you are correct, there is no notion of function at this level, just a CPU executing instructions in RAM. 0x0001080E is the current value of EIP. This is very low level debugging :)

Maybe an inspiration would be to look at how ghidra is handling this case. When connecting to GDB via ghidra, it will request memory around the program counter and build a disassembly view from that.

epasveer commented 1 year ago

Hi Kevin,

This is very low level debugging :) Yes, the dark art. :^)

I'll look at ghidra. Also, I think I may be able to duplicate the problem. I have a test assembly program but it has the notion of a "_start" function. So Seer is happy with that. Your code sounds even lowel-level than that.

I think I understand what's happening. I'll work on some things.

epasveer commented 1 year ago

I'm able to reproduce the problem. I've created a simple assembly program and then stripped all debug info from the binary.

I'll work on getting this fixed.

epasveer commented 1 year ago

Hi Kevin, others.

I've added a mode for the Assembly editor. See the Config dialog for Assembly.

image

It seems I was using gdb's disassembly command that took the $PC and figured out the start and end address for the function that $PC was in.

However, for pure assembly programs, or for executables that have their debug info stripped, this gdb command would fail. Thus leaving the Assembly editor empty.

gdb has another disassembly command that can take an address and length of bytes.

I've added a mode (Function or Lenght) to Seer where you can choose one or the other. If you use Length, you can specify the number of bytes to fetch in a go.

When you get to the end of that, the next "stepi" command will fetch the next N bytes of instructions.

I'm not totally happy with what I've done. Give it a try with the latest snapshot. Let me know.

Thanks for your input!

kevinferrare commented 1 year ago

So I rebuilt it, did the setup in the settings, and now I can see the assembly, this is pretty cool !!!

Breakpoints are working, I can view and edit registers:

image

Still a bit counter intuitive for new users I think, but it's working and usable, thank you for this, I am finally going to use seer in my debugging sessions instead of the command line!

One thing that would be cool would be to request new bytes when the user scrolls down in the view, and to allow the user to jump to a location so that he can set breakpoints there from this window, but this has nothing to do with this issue :)

epasveer commented 1 year ago

Thanks for the screenshot.

I see you figured out how to remove the right tabs (thread/stack info). If you don't care about the source/symbol info, you can drag up the variable/register info tab upwards. You'll be left with just a larger tab for viewing registers and values.

epasveer commented 1 year ago

I'll likely close this task and open a new task for the other suggestions.

To clarify.

to request new bytes when the user scrolls down in the view,

When scrolling down, you want more assembly to be shown after the current assembly? Extending it by some amount of bytes. The current assembly is not deleted. Just more is added when the scrollbar nears the end of the current assembly.

and to allow the user to jump to a location so that he can set breakpoints there

I can add a way to enter a new address to disassemble. Likely I'll make the "PC" field in the Assembly view editable. Once you visit another address to set a breakpoint, how would you want to go back to the current address?

Still a bit counter intuitive for new users

If you could expand on this, I'd appreciate it. There's lots I can do to make the experience better.

kevinferrare commented 1 year ago

Thank you for the tip, it's even better like that: image

Yes, this is what I meant. Here is my full feedback:

Sorry if this seems like a lot, but those are the things that came to my mind while using it.

And also I didn't say it, but thank you for creating this software!

I tried a lot of clients and this is the only GUI one that is usable in stub mode, I am actually very very happy :smile:

epasveer commented 1 year ago

Awesome! Thanks for the suggestions. I'll give them some thought and will create tasks for them.

epasveer commented 1 year ago

Closing this task. New discussion can happen in #127.