How to Debug MIPS Interactively - gdb

I'm taking a course on Computer Organization and Assembly.
In class, we're learning MIPS. This is for the purpose of introducing basic concepts, like pipelining. We're writing a handful of simple MIPS programs for class.
I'm used to gdb for debugging and learning, and the debugger we use in class is SPIM. SPIM sucks. It allows me to step through a program, but it doesn't allow me to interactively execute MIPS instructions at an arbitrary point of execution. I am immediately tired of having to exit SPIM, edit the source, and run SPIM again, navigating to the desired point of execution, only to see I have to do it again because I made yet another mistake.
Or perhaps I am mistaken and SPIM does allow this. My instructor said that this feature is not supported, so I'm going off what he said. I googled around a bit and didn't find a workaround.
I have tried googling for interactive MIPS debuggers like gdb but I haven't found any. I'm aware that gdb can debug MIPS programs, but I don't have a MIPS machine to run MIPS programs on.
I run Ubuntu in VMware. How can I interactively debug MIPS programs, using gdb or otherwise?
Edit: found some reference material on Mips.com on their recommended Linux Toolchain.

You can use qemu as an emulator, gdb as a debugger and gcc as a compiler. It's universal tool-set to investigate different architectures.
For Ubuntu you can install dependencies with followed command (probably, list is not full for your system - it's up to you there):
sudo apt install gdb-multiarch qemu qemu-user gcc-multilib gcc-multilib-mips64-linux-gnuabi64
Now you can use gcc as a compiler.
$ cat code.c
#include<stdio.h>
int main()
{
printf("Hello world!\n");
return 0;
}
$ mips64-linux-gnuabi64-gcc code.c -static -g3
And start emulation in qemu with debug session:
$ qemu-mips64 -g 1234 ./a.out
In gdb-multiarch use the following routine:
symbol-file a.out
set arch mips:isa64
target remote :1234
b main
c
And here is your goal:
(gdb) x/5i main
0x120003850 <main>: daddiu sp,sp,-32
0x120003854 <main+4>: sd ra,24(sp)
0x120003858 <main+8>: sd s8,16(sp)
0x12000385c <main+12>: sd gp,8(sp)
0x120003860 <main+16>: move s8,sp
I believe, you can adapt it for your tasks. And MIPS arch is so various, as you can see in gdb set arch command.

Related

Difference in threaded program speed when compiled using VSCode's terminal vs. Mac terminal M1

I'm using the same Makefile in both instances, which is basically c++ -std=gnu++2a -pthread -Wall -g -O3, and running on an Apple M1 MacBook Pro.
When compiled using the native terminal (zsh), my program runs in 67.XX seconds.
When compiled using VSCode's terminal (which is zsh), my program runs in 3.5X seconds.
Does anyone know why there is this difference when running multithreaded programs? The speed is exactly the same for non-multithreaded programs. I'm just confused why the same Makefile, compiled using a zsh terminal, but one using VSCode's terminal and the other using my native terminal would make such a big difference?
I would expect that with the same Makefile, the resulting program would be compiled the same way? I guess there is something big I'm missing here.
Edit1: Compiler: g++-12 (Homebrew GCC 12.1.0)
Edit2: I realized the difference was running my terminal using Rosetta so it was compiling to x86-64 in my native terminal,but arm in my VSCode terminal. Is the difference really that big for multithreaded programs in x86 vs ARM?

how to install kcachegrind on linux or cirrus?

I am working on a cirrus machine, having my C code profiled. I have Valgrind installed on it. But the output I get from --tool=callgrind is barely understandable, hence I want to use kcachegrind tool. But I am not able to find a link to install it on linux terminal/cirrus.
Cirrus is not the name of a machine is the name of the cluster you are trying to work on.
So once being there,
first you need to load the Valgrind module otherwise commands are not recognized by the compiler.
$ module load valgrind
Have a check here:
https://hpc-uit.readthedocs.io/en/latest/development/debugging.html

No matter what I tried, GDB just won't work on my Mac (Mojave). Common error but I've found no solutions

it's my first post so I apologise in advance if I post anything wrong or incorrectly format.
My system: MacBook Pro running MacOS Mojave 10.14.1, Netbeans 8.2
I'm running a simple C++ program that prints hello world:
int main(int argc, char** argv) {
cout << "Hello World" << endl;
return 0;
}
So my issue is that I cannot run the debugger on my MacBook using Netbeans or Terminal commands. Every time I do, I get the following error:
not in executable format: file format not recognized
I originally had the problem where I had a missing debugger command. I followed the directions here and installed Homebrew, got gdb, and code-signed the gdb binary. After all that I started getting the error highlighted above.
I google this new problem, and I find this stack overflow post which suggests that I might be running a 32-bit gdb while building in 64-bit. However, based on the output when running gdb:
GNU gdb (GDB) 8.2
Copyright (C) 2018 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.
Type "show copying" and "show warranty" for details.
This GDB was configured as "x86_64-apple-darwin18.0.0".
Type "show configuration" for configuration details.
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>.
Find the GDB manual and other documentation resources online at:
<http://www.gnu.org/software/gdb/documentation/>.
For help, type "help".
Type "apropos word" to search for commands related to "word"...
BFD: /Users/Anon/Desktop/gdb_test/gdb_test: unknown load command 0x32
BFD: /Users/Anon/Desktop/gdb_test/gdb_test: unknown load command 0x32
"/Users/Anon/Desktop/gdb_test/gdb_test": not in executable format: file format not recognized
And the configuration of the GDB:
This GDB was configured as follows:
configure --host=x86_64-apple-darwin18.0.0 --target=x86_64-apple-darwin18.0.0
--with-auto-load-dir=:${prefix}/share/auto-load
--with-auto-load-safe-path=:${prefix}/share/auto-load
--with-expat
--with-gdb-datadir=/usr/local/Cellar/gdb/8.2/share/gdb (relocatable)
--with-jit-reader-dir=/usr/local/Cellar/gdb/8.2/lib/gdb (relocatable)
--without-libunwind-ia64
--without-lzma
--without-babeltrace
--without-intel-pt
--disable-libmcheck
--without-mpfr
--with-python=/System/Library/Frameworks/Python.framework/Versions/2.7
--without-guile
--with-separate-debug-dir=/usr/local/Cellar/gdb/8.2/lib/debug (relocatable)
("Relocatable" means the directory can be moved with the GDB installation tree, and GDB will still find it.)
It seems that my GDB is indeed 64-bit so I'm guessing that's not the problem. I also found this post where the top answer suggests that gdb 8.2 is impossibly broken and I should just downgrade to 8.0.1. However, an edit says that an update by the GNU team has (supposedly) fixed the problem so I run:
brew update
and ensure that everything is up-to-date, but I still get the same error.
I'm at my wits end here, and I've put in WAY too much time into trying to resolve this issue. If it can't be fixed, can you suggest other hassle-free ways (massive emphasis on hassle-free) I can debug C/C++ programs on my Mac? Otherwise, I'll stick to my university's computer labs.
EDIT: here's how I compiled from the terminal
g++ -g main.cpp -o main
I'm compiling in Debug mode (64-bit) in Netbeans with C++14 standard using the g++ compiler.
I call gdb after compiling by writing to the terminal:
gdb main
or by simply using the GUI in Netbeans
The compilers on macOS are confusing. Apple supplies the LLVM compiler as part of Xcode, but it provides a stub at /usr/bin/g++ which leads people to believe they are using GCC, i.e. the GNU Compiler Collection. They then try to use gdb, i.e. the GNU Debugger with the LLVM-produced executables and find it doesn't work.
IMHO, you either need to use wholly Apple-supplied tools, or wholly GNU-supplied tools.
So, let's look at the first option - using Apple tools. In this case you compile with:
/usr/bin/g++ -g main.cpp -o main
and debug with:
/usr/bin/lldb ./main
and the debugger commands seem pretty similar to GDB.
The second option is using GCC and GDB which are normally best installed using homebrew. The installation commands are:
brew install gcc
brew install gdb
Then you will compile with something like:
/usr/local/bin/g++-8 -g main.cpp -o main
and debug with something like:
/usr/local/bin/gdb ./main
However, I cannot get this to work on macOS Mojave for the moment! I read here that GDB v8.1 doesn't work on macOS and you need to install v8.0.1 instead but cannot seem to do that with homebrew.

How do I perform a remote gdb session on a PC for ARM gdbserver WITH GDB GUI frontend?

I am using Ubuntu 16.04 on x86_64 workstation, and I'm cross-compiling a small demo program in C++, and deploying it to an embedded linux target running ARM architecture (environment-setup-cortexa9hf-neon-poky-linux-gnueabi, arm-poky-linux-gnueabi-g++).
I am able to successfully do this which gives me a debug session on commandline:
Target:
rpm -ivh gdbserver-7.10.1-r0.cortexa9hf_neon.rpm
gdbserver :9091 ${APPNAME}
Host:
sudo apt-get install gdb-multiarch
gdb-multiarch $APPNAME
target remote 192.168.0.212:9091
...
I can now use gdb-multiarch on commandline!
However from here... I really want to be able to use one of the many gdb frontend tools to provide a GUI to set breakpoints and step through the code (akin to gdbgui, or using vscode and configuring for a debugger). Are there any gdb frontend tools that specifically support gdb-multiarch?
Any tool I try, I believe no matter what it uses base gdb executable and gives this error because of mismatched architecture:
target remote 192.168.0.212:9091
Remote debugging using 192.168.0.212:9091
warning: Architecture rejected target-supplied description
Remote 'g' packet reply is too long: 0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000070fdff7e00000000c0fafc76100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
UPDATE 1 --
I can kinda sorta get this to work using ddd tool:
ddd --eval-command="target remote $MY_TARGET_IP:9091" --debugger gdb-multiarch
However! This is ancient and buggy, and I can't set breakpoints in loaded .so's right now with this.
I tried gdbgui with its options to specify debugger, but that's not currently working either. I filed a feature request report here:
https://github.com/cs01/gdbgui/issues/237
I found a way using gdbgui, but it required me to rebuild gdb from source code against my specific remote target architecture. Details of how I got it to work are here:
https://github.com/cs01/gdbgui/issues/237
Important bits in case the above link breaks:
TLDR Solution:
I was trying to rely on a prebuild gdb-multiarch from ubuntu apt repos, which didn't work. When I decided to download gdb and rebuild from source while configuring for arm-linux-gnuabi target arch.
Build method:
downloaded latest gdb source code
unzip it, go into folder, and build it like this:
./configure --host=x86_64-pc-linux-gnu --build=x86_64-pc-linux-gnu --target=arm-linux-gnuabi && make -j8 && sudo make install
Important to note that for my particular remote gdb server it's running on ARM so i had to say target=arm-linux-gnuabi in configure. GDB is building for my PC x86 arch, but it knows when debugging to recognize the target as ARM!
Now, arm-linux-gnuabi-gdb is installed by default to /usr/local/bin ... but you can instead provide prefix=<path> to where you want it to install in ./configure script above.
Using this, I was able to build a secondary copy of gdb called arm-linux-gnuabi-gdb which i could feed to gdbgui like this:
gdbgui -g arm-linux-gnuabi-gdb
From there, I can give gdb commands to connect to my remote gdbserver. I'm having to set breakpoints beforehand. My gdb commands are like this to set a few breakpoints:
set breakpoint pending on
break my_object.cpp:<line number for breakpoint>
b example_function_name
target remote <remote arm machine IP>:<gdbserver port>
c
Works great! This is leaps and bounds better than running gdb on commandline on my remote target.

Is it possible to use gdb to debug remotely over ssh?

Can I debug a program running on a remote target to which I have ssh access, using local source files?
Say I've got a program called hello.c, in directory /home/jla/hello on my home machine.
And on the remote machine I put this same file in a directory /hello, and compile it with
$ gcc -g -o hello hello.c, and then delete the remote hello.c, but leave the executable.
Can I then run gdb locally, get it to ssh in to the remote machine to run the executable, but use the local sources as reference?
Notes:
Annoyingly, the remote machine is very stripped down and can't be altered. It has gdb, but it doesn't have gdbserver
Note that the local and the remote machine have different architectures. In this particular case 64bit and 32bit intel
What I really want to do is run it under emacs/gud. But this would be a great start.
The architectures of remote and local machines matter very little. What matters is how hello, gdb and gdbserver are built.
It sounds from your description that hello is built (on remote machine) for x86_64-linux-gnu
That means you need x86_64-linux-gnu gdbserver, and also a 32-bit GDB that is capable of debugging x86_64 binaries. You should be able to build both, copy gdbserver to the remote machine, and debug "normally".