5

My computer run with Ubuntu 14.04. GDB seems to be abnormal in different account. For example I make a very simple test. I write a file under ~/test/test.c like this:

#include <stdio.h>
#include <stdlib.h>

int main(int argc, char *argv[])
{
    printf("hello,world");
    return 0;
}

and build with command "gcc -g test.c -o test", then I get result file named test. Next step, run gdb to debug. Notice that current account is user of my own.

$gdb test
(gdb)l      //work well
(gdb) b 6   //work well
(gdb) r     //error: Cannot exec /home/xxx/test/test -c exec /home/xxx/test/test .
            //Error: No such file or directory

But if I change to root account by command "su", gdb works well. Why?

  • 2018 gdb still has that problem, shows in ddd too. you may need to place export SHELL at the top of .bashrc rather than the bottom. – j mp Jun 21 '18 at 21:39
3

It appears that your SHELL variable is set to a file that doesn't exist. Try the following:

export SHELL=/bin/sh
gdb test

ensuring that /bin/sh exists and is executable. This works via su not because of root permissions, but because su resets the SHELL environment variable. Per the su manual page:

Note that the default behavior for the environment is the following:

The $HOME, $SHELL, $USER, $LOGNAME, $PATH, and $IFS environment variables are reset.

Further Discussion

If you are asking yourself, "How was I supposed to know that from the following error message?":

//error: Cannot exec /home/xxx/test/test -c exec /home/xxx/test/test .
//Error: No such file or directory

You are not alone. This appears to be poor error reporting from gdb. When gdb decides that it needs to execute your command using a shell, it constructs a command in the following format:

/path/to/shell -c exec /path/to/executable

However, when it prints the error message, it does this:

  save_errno = errno;
  fprintf_unfiltered (gdb_stderr, "Cannot exec %s", exec_file);
  for (i = 1; argv[i] != NULL; i++)
    fprintf_unfiltered (gdb_stderr, " %s", argv[i]);
  fprintf_unfiltered (gdb_stderr, ".\n");
  fprintf_unfiltered (gdb_stderr, "Error: %s\n",
                      safe_strerror (save_errno));
  gdb_flush (gdb_stderr);

Here exec_file is the expanded path of the file you passed on the command line. It prints exec_file first, followed by the elements of argv, starting at the 1st index. argv contains the arguments it passed to execvp.

Unfortunately, the shell it is trying to use is in the 0th element of argv, which never gets printed. Thus, you never see the file that execvp couldn't find.

Further, it then prints a trailing . which isn't actually one of the arguments that it passed to execvp and is presumably there to make the message a completely sentence.

Finally, it prints the error we got back from our call to execvp, which is that the executable file could not be found.

This bug likely is caused by the fact that this error handling code is the same for the case where gdb attempts to exec the command directly and for the case when it uses the shell. In the former case, the constructed error message would look correct since exec_file and argv[0] would be the same.

  • Why does it need to use the shell to execute the command? – Barmar Nov 14 '14 at 19:07
  • @Barmar It doesn't need to, but it does so to make it easier for the user. For instance, it allows you to specify command arguments that can be expanded by the shell (for instance globs such as * in paths). In gdb 7.7 or greater, set startup-with-shell false will tell gdb to exec your program directly. In versions older than that, it is a compile-time option. – Steven D Nov 14 '14 at 20:53

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.