gdb - how to make it call a program with a relative name [duplicate] - gdb

I am trying to launch a legacy application in GDB, and it requires that it's argv[0] value not contain anything other than alphanumeric characters.
Whenever I launch the program in GDB it seems that it expands the name to be the full path before running the program, so I get an error like (because it can't deal with the slashes):
"Cannot find /home/user/myapp ..."
Is it possible to run a program in GDB with a relative path, so that it will just see "myapp"?

Gdb normally runs target commands using the shell command line
exec program_pathname program_arguments
But it has a set exec-wrapper command that will change this to
exec exec_wrapper program_pathname program_arguments
The exec_wrapper is often another command, but it can be an option that the exec command accepts.
Many shells (bash, zsh, ksh93) support a -a option to the exec command to set argv[0].
So, if your shell supports exec -a, you can do the following to invoke /home/user/myapp with argv[0]==myapp:
(gdb) set exec-wrapper -a myapp

Related

What shell does std::system use?

TL;DR; I guess the shell that std::system use, is sh. But, I'm not sure.
I tried to print the shell, using this code: std::system("echo $SHELL"), and the output was /bin/bash. It was weird for me. So, I wanted to see, what happens if I do that in sh? And, the same output: /bin/bash. Also, if I use a command like SHELL="/usr/bin/something", to set the SHELL variable to another string, it will print the new string that I set to it (/usr/bin/something), and it looks it's not a good way to see what shell it's using. Then, I tried to check it, using the ps command, and the output was: bash, a.out, ps. It was weird to see bash in this list. So, I created a custom shell, and change the shell in gnome-terminal to it:
#include <iostream>
int main()
{
std::string input;
while (true)
{
std::string command;
std::getline(std::cin, command);
std::system(command.c_str());
}
}
Now, it's easier to test, and I think, the results is better.
Then, I tried to test the ps command again, but in the custom shell, and the results was: test_shell, ps.
It was weird again. How the shell isn't sh, nor bash? And, the final test I did was: echo $0. And, the results was sh, in both custom shell, and normal program.
Edit
It seems like /bin/sh is linked to /bin/bash (ll /bin/sh command's output is /bin/sh -> bash), and actually, it seems like the only difference between sh and bash is filename, and the files's contents are the same. I checked the difference between these files with diff command too:
$ xxd /bin/sh > sh
$ xxd /bin/bash > bash
$ diff sh bash
(+ Yes, $SHELL doesn't means the running shell (I didn't know that when I was testing, and I just wanted to see what happens))
The GNU sources (https://github.com/lattera/glibc/blob/master/sysdeps/posix/system.c) say
/bin/sh
So, whatever /bin/sh is hardlinked to is the shell invoked by std::system() on Linux.
(This is correct, as /bin/sh is expected to be linked to a sane shell capable of doing things with the system.)
According to cppreference.com, std::system
calls the host environment's command processor (e.g. /bin/sh, cmd.exe, command.com)
This means the shell used will depend on the operating system.
On any POSIX OS (including Linux), the shell used by std::system is /bin/sh. (Though as the OP points out, /bin/sh could be a symlink to another shell.)
As for the SHELL environment variable, as has been pointed out in the comments, this environment variable cannot be used to reliably identify the running shell program. SHELL is defined by POSIX to
represent a pathname of the user's preferred command language interpreter
(source)

How can I debug a C program installed using guix?

I installed flatpak using guix, but it segfaulted on startup. I wanted to debug it, but guix installs a wrapper script for flatpak, so I get this error when trying to run it under gdb:
"/home/user/.guix-profile/bin/flatpak": not in executable format: file format not recognized
and I tried to edit the wrapper script to call gdb, but this wrapper script is not even editable by root, because it is owned by root and has read-only permissions.
Simply copy the script to your current working directory:
cp /home/user/.guix-profile/bin/flatpak .
Mark it as writable:
chmod +w flatpak
Edit the script with your favourite text editor, to replace the string exec -a with exec gdb --args.
And finally, run it with any arguments you provided before, when it misbehaved:
./flatpak remote-add flathub https://flathub.org/repo/flathub.flatpakrepo
In this particular case, this wasn't immediately super-useful, because a debug symbol output hasn't been built for this package. But at least I could get a backtrace out of gdb.

How to run iostream system command in the same thread?

I'm trying to execute a command using std::system from Unreal Engine C++
FString command = FString("start /B cmd /k python \"D:/app.py\"");
std::string comm(TCHAR_TO_UTF8(*command));
std::system(comm.c_str());
The command itself is working as expected, however, I need it to execute on the current thread, or alternatively check if it's finished before continuing because the next operations depend on the completion of this command
Is there a way to do it? or maybe I should use another command?
Thanks, Eden
The std::system function will not return until the command you execute have finished running.
Also on Windows (which you seem to be running) then system will invoke the command interpreter (cmd) for execution of the command, which means the command you want to execute must be in the command interpreters PATH (or be an internal command of the command interpreter).
If python is in the PATH, then you could run the python command directly, without using start or cmd (especially since then you would have two instances of cmd running), and the system function would block and not return until the python command finished running:
FString command = FString("python \"D:/VRoscopy_repo/VRoscopy/conversion/invesalius3-master/app.py\" --no-gui -i \"D:\VRoscopy_repo\DICOM\Human\MedDream\Body\" -t 200,3033 -e \"D:\VRoscopy_repo\DICOM\Human\MedDream\Body/VRoscopy27777BED4B650CE6AFE884B365C56BCC.stl\"");

Hiding console command used while using system()? C++ Linux

Well, I will put it plain and simple: I am a C++ pleb. Still trying to learn though.
My question is: is it possible to run a command though the terminal using system() command without letting the command be shown in the console/terminal?
Example:
system("sudo service sshd start") ;
Output: Sudo service sshd start
Where as I want:
system("sudo service sshd start") ;
output: (Blank)
Note: I am on linux.
The system standard library function starts up a subshell and executes the provided string as a command within that subshell. (Note that a subshell is simply a process running a shell interpreter; the particular shell interpreter invoked by system will depend on your system. No terminal emulator is used; at least, not on Unix or Unix-like systems.)
The system function does not reassign any file descriptors before starting the subshell, so the command executes with the current standard input, output and error assignments. Many commands will output to stdout and/or stderr, and those outputs will not be supressed by system.
If you want the command to execute silently, then you can redirect stdout and/or stderr in the command itself:
system("sudo service sshd start >>/dev/null 2>>/dev/null") ;
Of course, that will hide any error messages which might result from the command failing, so you should check the return value of system and provide your own error message (or log the information) if it is not 0.
This really has very little to do with the system call or the fact that you are triggering the subshell from within your own executable. The same command would have the same behaviour if typed directly into a shell.

How to run gdb with LD_PRELOAD?

I have a program using LD_PRELOAD. The program should be run like
this, "LD_PRELOAD=/path/to/libfoo.so qemu -U LD_PRELOAD a.out", if
without gdb.
Here are what I did while running gdb.
(gdb) set environment LD_PRELOAD=/nfs_home/chenwj/tools/lib/libdbo.so
(gdb) file /nfs_home/chenwj/tools/bin/qemu-i386
(gdb) r -U LD_PRELOAD bzip2_base.i386-m32-gcc44-annotated input.source 1
But gdb gave me the error below
Starting program: /nfs_home/chenwj/tools/bin/qemu-i386 -U LD_PRELOAD bzip2_base.i386-m32-gcc44-annotated input.source 1
bash: open "/bin/bash" failed: Permission denied
During startup program exited with code 66.
Any sugguestion appreciated.
Regards, chenwj
GDB does not invoke your executable directly. Instead, it does
bash -c '/nfs_home/chenwj/tools/bin/qemu-i386 -U LD_PRELOAD bzip2_base.i386-m32-gcc44-annotated input.source 1'
This is done so that bash takes care of I/O redirection (which you are not using).
My guess is that /bin/bash doesn't work when LD_PRELOAD=libdbo.so is in effect, though I don't understand the exact nature of failure.
One way to work around this problem is to create a wrapper executable, implementing C equivalent of this:
export LD_PRELOAD=/nfs_home/chenwj/tools/lib/libdbo.so
exec /nfs_home/chenwj/tools/bin/qemu-i386 "$#"
and debug that executable (without setting LD_PRELOAD). You'll see an extra SIGTRAP when the wrapper execve()s the wrapped qemu-i386, which you should ignore and continue.