How can I debug QEMU with one terminal? - c

I am working on a moon rover for Carnegie Mellon University which will be launching next year. Specifically, I am working on a flight computer called the ISIS OBC (On Board Computer) and I am trying to find out how to first run QEMU in a terminal in the background, and then run GDB to connect to the QEMU instance I just backgrounded. I have tried running QEMU in the background with & as well as using the flag -daemonize but this causes QEMU's GDB server to not work at all.
The overarching goal is to be able to debug our flight software in GDB in one terminal window so that I can run it from inside a Docker container mounted on the repository's root. It takes a bit of setup to get be able to debug our code, with a couple of gotchas like incompatibility with newer versions of GCC, so being able to run the CODE and debug it from inside a Docker container (which has all our other development dependencies installed too) is a must.
My current solution was to just run QEMU in another gnome-terminal I initialized in the startup script completely outside of the docker container, but this will not work in Docker for obvious reasons. Here is that code in case the additional context is helpful:
#!/bin/bash
#The goal of the below code is to get the stdout from QEMU piped into GDB.
#Unfourtunately it appears that QEMU must be started as the FG in its own window so that it will
#start its GDB server, so an additional window is required.
my_tty=$(tty)
gnome-terminal -- bash -c './../obc-emulation-resources/obc-qemu/iobc-loader -f sdram build/app.isis-obc-rtos.bin -s sdram -o pmc-mclk -- -serial stdio -monitor none -s -S > /tmp/qemu-gdb; $SHELL' --name="QEMU-iOBC" --title="QEMU-iOBC" -p
tail -f /tmp/qemu-gdb > $my_tty&
./third_party/gcc-arm-none-eabi-10.3-2021.07/bin/arm-none-eabi-gdb -ex='target remote localhost:1234' -ex='symbol-file build/isis-obc-rtos.elf'
# Kill any leftover qemu debugging sessions
kill $(ps aux | grep '[i]obc-loader' | awk '{print $2}')
# Delete intermediate file
rm -f /tmp/qemu-gdb
# Get's rid of any extra text that may occur
echo ""
clear
I would much prefer to run something like this to achieve my goal:
./../obc-emulation-resources/obc-qemu/iobc-loader -f sdram build/app.isis-obc-rtos.bin -s sdram -o pmc-mclk -- -serial stdio -monitor none -s -S > /tmp/qemu-gdb
rather than what I am running now:
gnome-terminal -- bash -c './../obc-emulation-resources/obc-qemu/iobc-loader -f sdram build/app.isis-obc-rtos.bin -s sdram -o pmc-mclk -- -serial stdio -monitor none -s -S > /tmp/qemu-gdb; $SHELL' --name="QEMU-iOBC" --title="QEMU-iOBC" -p
"iobc-loader" is a wrapper used to run the QEMU command by the way."app.isis-obc-rtos.bin" is of course the binary I am trying to run and "isis-obc-rtos.elf" contains the symbols used to debug it. Apologies if the answer is obvious, I am a student!

You can try using a terminal multiplexer like screen or tmux, which allow you to run each command in foreground in a separate virtual terminal.
You can also create panes, for example with tmux press Ctrl+b " to split the screen horizontally or Ctrl+b % to split it vertically, then Ctrl+b o to cycle between them.

Using tmux is definitely the easiest approach, especially with its built in CLI support.
You could write a script similar to this one:
tmux start-server
tmux new-session -d -s debug-session -n isis -d "<cmd1>";"<cmd2>"
Where cmd1 is your QEMU execution script, and cmd2 is another script that runs the docker you want to use for debugging.

Related

catch console output from background process

I have a program running on armbian single board computer. The program starts with -b option during the startup of the system. I created this simple shell script
#!/bin/bash
#Myprog server start
sudo -b /home/myprog/myprog
This program is C written and it sometimes outputs some information with printf functions. But since it is started with -b option there's is noting in the console.
Now when I log in to the armbian via ssh with Putty I want to occasionally read the output of this program. Is it even possible?
Not exactly what you’re asking, but generally speaking it’s better practice to redirect output to a log file than to try to interactively look at the console output for a background app.
Something like:
sudo -b /home/prog/myprog >> /home/prog/log.txt 2>&1
Should do it.
Then view output with
tail -f /home/prog/log.txt
If it’s really important to you to run interactively without logs, I would suggest running it from within “screen” without backgrounding it.
screen
sudo /home/prog/myprog
Then ctrl-d to detach and let it run in background. screen -r to reattach.

How to disable messages to console during boot of Coral Dev Board?

I have purchased a coral dev board. The output of messages to the console during boot seem to add about 1 second to the boot time, therefore I want to disable the console or reduce the number of messages written to the console. To achieve this I have tried two different things.
I have set the bootargs parameter in U-Boot to pass quiet as kernel parameter to silence the console using these commands:
setenv bootargs quiet
saveenv
I have also added the following lines to U-Boot config file imx8mq_phanbell.h:
CONFIG_SILENT_CONSOLE
CONFIG_SILENT_CONSOLE_UPDATE_ON_SET
CONFIG_SYS_DEVICE_NULLDEV
Then I have rebuilt u-boot and flashed it to the board and set the u-boot variable silent to 1.
Neither of these changes have had any effect on the output from the console during boot.
Can you help me with this problem?
I have solved my issue by first adding the quiet parameter to the cmdline variable defined in the file boot.txt found here: https://coral.googlesource.com/build/+/refs/heads/docker/boot.txt.
Then I compiled boot.txt to a script image file with the mkimage tool and replaced boot.scr used by U-Boot in /boot with this file.
This does indeed reduce boot time.
Thanks Fredrik for the response, to reiterate but this works for any kernel params that needs to be added:
Download boot.txt:
$ curl https://coral.googlesource.com/build/+/refs/heads/docker/boot.txt\?format\=TEXT | base64 --decode | tee boot.txt > /dev/null
Install mkimage:
$ sudo apt install u-boot-tools
Make your necessary changes in the cmdline="" line, for this example, we need to add "quiet loglevel=0":
cmdline=<preexsisting> + quiet loglevel=0
compile to boot.scr:
$ mkimage -A arm -T script -O linux -d boot.txt boot.scr
replace boot image file
$ mv boot.scr > /boot
Reboot and the new kernel params should be loaded.

How to disable linux space randomization via dockerfile?

I'm trying to disable randomization via Dockerfile:
RUN sudo echo 0 | sudo tee /proc/sys/kernel/randomize_va_space
but I get
Step 9 : RUN sudo echo 0 | sudo tee /proc/sys/kernel/randomize_va_space
---> Running in 0f69e9ac1b6e
[91mtee: /proc/sys/kernel/randomize_va_space: Read-only file system
any way to work around this? (I see its saying read-only file system any way to get around this?) If its something which the kernel does this means it's outside of my container scope, in that case how am i supposed to work with gdb inside my container? please note this is my target to work with gdb in a container because i'm experimenting with it, so i wanted a container which encapsulates gcc and gdb which i'll use for experimentations.
In host
run:
sudo echo 0 | sudo tee /proc/sys/kernel/randomize_va_space
not in docker
Docker has syntax for modifying some of the sysctls (not via dockerfile though) and kernel.randomize_va_space does not seem to be one of them.
Since you've said you're interested in running gcc/gdb you could disable ASLR only for these binaries with:
setarch `uname -m` -R /path/to/gcc/gdb
Also see other answers in this question.
Sounds like you are building a container for development on your own computer. Unlike production environment, you could (and probably should) opt for a privileged container. In a privileged container sysfs is mounted read-write, so you can control kernel parameters as you would on the host. This is an example of Amazon Linux container I use to develop for on my Debian desktop, which shows the difference
$ docker run --rm -it amazonlinux
bash-4.2# grep ^sysfs /etc/mtab
sysfs /sys sysfs ro,nosuid,nodev,noexec,relatime 0 0
bash-4.2# exit
$ docker run --rm -it --privileged amazonlinux
bash-4.2# grep ^sysfs /etc/mtab
sysfs /sys sysfs rw,nosuid,nodev,noexec,relatime 0 0
bash-4.2# exit
$
Notice ro mount in the unprivileged, rw in the privileged case.
Note that the Dockerfile command
RUN sudo echo 0 | sudo tee /proc/sys/kernel/randomize_va_space
makes no sense. It will be executed (a) during container build time (b) on the machine where you build the image. You want (a) happen at container's run time and (b) on the machine where you run the container. If you need to change sysctls on image start, write a script which does all the setup and then drops you into the interactive shell, like placing a script into e.g. /root and setting it as the ENTRYPOINT
#!/bin/sh
sudo sysctl kernel.randomize_va_space=0
exec /bin/bash -l
(Assuming you mount host working directory into /home/jas that's a good practice, as bash will read your startup files etc).
You need to make sure you have the same UID and GID inside the container, and can do sudo. How you enable sudo depends on a distro. In Debian, members of the sudo group have unrestricted sudo access, while on Amazon Linux (and, IIRC, other RedHat-like system, the group wheel has. Usually this boils down to an unwieldy run command that you rather want to script than type, like
docker run -it -v $HOME:$HOME -w $HOME -u $(id -u):$(id -g) --group-add wheel amazonlinux-devenv
Since your primary UID and GID match the host, files in mounted host directories won't end up owned by root. An alternative is create a bona fide user for yourself during image build (i.e., in the Dockerfile), but I find this more error-prone, because I can end up running this devenv image where my username has a different UID, and that will cause problems. The use of id(1) in a startup command guarantees UID match.

Editing .desktop file to run executable as root?

I have compiled a c program into an executable that I would now like to integrate into the applications menu in Debian 7.4 XFCE. In order to run the application under normal circumstances, I am required to type
sudo myprogram
Now I have created my .desktop file and placed it in /usr/share/applications
[Desktop Entry]
Type=Application
Encoding=UTF-8
Name=myprogram
Comment=configuration loader
Exec=sudo loader
Icon=/usr/share/icons/hicolor/48x48/apps/myprogram.png
Terminal=false
Categories=Development;IDE
The item is added to my applications menu as expected, and the icon shows up properly. The problem, however, is that double clicking the menu item to launch the application does nothing.
If I navigate to /usr/bin (where I have placed my executable) and type "sudo myprogram", the program launches as expected.
What can I do to fix this issue and get the program to launch from the menu? Perhaps /usr/bin is not the correct place to put it, or I have the incorrect Exec command. I greatly appreciate the help.
I ended up using (after installing gksu)
Exec = gksu myprogram
this launches a graphical sudo prompt, which is sufficient for my needs.
This is what the setuid bit in the permissions is for. It makes executables run with permissions of the file owner. This only works on actual executables, not on shell scripts!
sudo chmod u+s myprogram
sudo chown root myprogram
./myprogram # now runs as root
Please be careful when using this as it will always execute that program as root no matter who executes it. You can limit access by setting it to your usergroup and deny all execute.
chgrp "${USER}" myprogram # provided you have individual groups set up
chmod a-x myprogram # deny all execute
This approach does not need additional installation of packages.
Terminal=true opens a new terminal window which runs
sudo -i to ask for the password.
Then, using sh to run the program, the Terminal is closed and myprogram runs in the background because it has a & at the end.
[Desktop Entry]
Type=Application
Name=...
Exec=sudo -i sh -c "myprogram &"
Terminal=true
Request: Please report if it works under your OS.
Tested under:
Xubuntu
The pkexec solution from askubuntu:
Exec=pkexec env DISPLAY=$DISPLAY XAUTHORITY=$XAUTHORITY APP_COMMAND
Try adding this to .desktop
Path=/path/to/myprogram

PostgreSQL installation as a user on Cygwin

I'm trying to install PostgreSQL on Cygwin as a user following the instructions given in the cygwin package installation:
cygrunsrv -S cygserver
initdb -D /usr/share/postgresql/data
pg_ctl start -D /usr/share/postgresql/data -l /var/log/postgresql.log
createdb
psql
After I do the third step, I get the following output in the terminal,
$ postgres -D /usr/share/postgresql/data
LOG: database system was shut down at 2013-04-12 19:04:33 PDT
LOG: autovacuum launcher started
LOG: database system is ready to accept connections
After that, I'm unsure on what to do since I never see the command line again(the "$" sign). I'm a complete beginner when it comes to databases, so are there any 'for dummies' pointers for me?
Use pg_ctl -D /usr/share/postgresql/data -l /path/to/write/log/to start if you want the server to start up and background its self.
I strongly recommend reading the PostgreSQL tutorial and manual, which cover this in detail.

Resources