Debugging program running another program [closed] - c

Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
Questions asking for code must demonstrate a minimal understanding of the problem being solved. Include attempted solutions, why they didn't work, and the expected results. See also: Stack Overflow question checklist
Closed 9 years ago.
Improve this question
I wrote a shell in C. There are some problems while running some programs on it.How can I run a program on a shell while debugging the shell in the gdb?

First use -g option to compile with debugging flags, for use with gdb.
Then run.
gdb shellapp
...
run someapps
...
For a quick reading How to Debug C Program using gdb in 6 Simple Steps and GDB Tutorial
Or do you mean run a program in the background?

You can attach by gdb to already running shell process from another console. This way your shell output will not interfere with gdb output and you can run programs in shell as usual.
Run your implementation of shell in 1st console window
Open 2nd console and find pid number of already running shell using ps command
Start gdb in 2nd console and attach to shell using it's pid number like this:
:~$ gdb -q
(gdb) attach 3479
Attaching to process 3479
Now you can set breakpoints and continue shell execution:
(gdb) b SomeFunction
(gdb) c
Continuing.
From this point you have 2 consoles:
the one where your shell is running
and the second where gdb runs attached to shell
You can use shell as usual: run other programs on it or do whatever else. And at the same time you can observe shell execution in 2nd console inside gdb. The point is that output of these 2 processes are separated from each other which would be impossible if you run shell directly inside gdb in just one console.

Related

How to provide options to program with GDB? [duplicate]

This question already has answers here:
How do I run a program with commandline arguments using GDB within a Bash script?
(9 answers)
Closed 2 years ago.
I have to debug a program that has errors in it as part of my assignment. However, I must first pass command line arguments in order to solve this problem.
I do:
gdb -tui InsertionSortWithErrors
which works, but after that I don't know how to pass arguments. I used gdb -help and it says something about --args which I also tried and it didn't work.
I want to be able to get the debugger+the GUIand pass command line arguments.
Once gdb starts, you can run the program using "r args".
So if you are running your code by:
$ executablefile arg1 arg2 arg3
Debug it on gdb by:
$ gdb executablefile
(gdb) r arg1 arg2 arg3
Try
gdb --args InsertionSortWithErrors arg1toinsort arg2toinsort
Another option, once inside the GDB shell, before running the program, you can do
(gdb) set args file1 file2
and inspect it with:
(gdb) show args
I'm using GDB7.1.1, as --help shows:
gdb [options] --args executable-file [inferior-arguments ...]
IMHO, the order is a bit unintuitive at first.

How do you debug a C program on Windows?

I've never used a debugger and the time has come to give them a try. MinGW appears to come with GDB which I've been trying to use. Supposdly running gdb from the command line and typing run myprog.exe starts the debugger but when I do this I get
Starting program: C:\MinGW\bin\myprog.exe MyProg.exe
[New Thread 1828.0xd8c]
Error opening file.
[Inferior 1 (process 1828) exited with code 02]
How to proceed or what's an easier way?
In particular I'm trying to flush out undefined behavior.
Since your program terminates, you'll need to set a breakpoint to see anything. Try break main before the run line. Then you can do commands line next (next line), step (step into/outof function calls), print expression (where expression can be a variable name or a function-call or a calculation), display expression (same as print, but prints just before each prompt). At any given point you can type backtrace to get a call stack. You can even type up and down to move up the callstack, so you can print higher local variables.
Well, the easiest way would be to use an IDE, actually. You might want to give code::blocks a try - very easy to use, configures everything for you on installation (just make sure to pick a compiler - don't worry, it'll prompt you) and there, you're all set and ready to go. As it's multi-platform, it doesn't really lock you into windows either, and gives you very powerful (and, I guess more importantly, convenient) possibilities of graphical debugging.
pass the binary with gdb
gdb <binary>
then set breakpoint to main
gdb) break main
Then run your program in gdb
gdb) run
then break point hits use 'n' or 'next' to step to different lines
gdb) n
Use 's' for stepping into function and 'p' printing var value
Example :
gdb) s <fun_name>
gdb) p x
I would suggest , as a beginner start off with Visual Studio. It has a very good and easy to use debugger. Just create a break point in the line from which you want to start debugging (click on the left bar beside the line or right click and create a break point). Once your break points are set you can just simply run the program in debug mode and the execution of the program will halt in the point where the break was created.
At this point you should be able to view all valuable information about the execution of the program. You can use F10 to continue the execution step or F11 to step inside the execution tree.
The debugger as many other advanced features like break on condition , hit count etc but you can start off with it's basic functionality.
If I compiled a program like this:
gcc -o my-prog -g myprog.c
I could then debug the executable my-prog it like this:
gdb my-prog
The -g option tells gcc to generate full debugging info. Other compilers will have their own versions of this option (e.g. the MSVC cl command has the /Zi option).
Since you're having issues running the gdb on your program, it might be worth checking if it was compiled with debugging info in the first place. The debugging info is usually generated in the same location as where you compiled your program.

How to use gdb with LD_PRELOAD

I run a program with LD_PRELOADing a specific library. Like this.
LD_PRELOAD=./my.so ./my_program
How do I run this program with gdb?
Do the following.
gdb your_program
(gdb) set environment LD_PRELOAD ./yourso.so
(gdb) start
Posting because we ran into a case where set environment didn't work:
From GDB documentation:
set exec-wrapper wrapper
show exec-wrapper
unset exec-wrapper
When ‘exec-wrapper’ is set, the specified wrapper is used to launch programs for debugging. gdb starts your program with a shell command of the form exec wrapper program. Quoting is added to program and its arguments, but not to wrapper, so you should add quotes if appropriate for your shell. The wrapper runs until it executes your program, and then gdb takes control.
You can use any program that eventually calls execve with its arguments as a wrapper. Several standard Unix utilities do this, e.g. env and nohup. Any Unix shell script ending with exec "$#" will also work.
For example, you can use env to pass an environment variable to the debugged program, without setting the variable in your shell's environment:
(gdb) set exec-wrapper env 'LD_PRELOAD=libtest.so'
(gdb) run
A way to set both the environment and arguments in one command:
gdb --args env LD_PRELOAD=/usr/local/lib/libstderred.so /usr/bin/ls -l
This uses env to the same effect as an exec wrapper (like Alexey Romanov's answer), except that GDB doesn't know about it. The side effect is that your session will start in env. Fortunately, GDB will follow the exec into the target program as if nothing happened, and the backtrace is identical.
The convenience of having everything in one command is that your shell history will help you run the exact same thing again.
You can supply env as an exec-wrapper on the command line using the -iex flag:
gdb -iex "set exec-wrapper env LD_PRELOAD=./my.so" ./my_program
I am using gdbserver with VS Code, the simplest way is launching your program wrapped in a shell:
gdbserver :8888 sh -c 'LD_PRELOAD=/libtest.so your_prog'
You can basically do it the same way, just add gdb before the program name:
LD_PRELOAD=./my.so gdb ./my.program
You can check the environment variables using:
(gdb) show environment LD_PRELOAD
In the rare case you actually need to change it inside gdb, e.g. when debugging a dlopen(), you ca do that:
(gdb) set environment LD_PRELOAD ./my.so
Oh, wait, it doesn't work for me with gdb 7.6.2! The library doesn't get loaded, that means none of the answer here are entirely correct, at least with current tools.

How do I find segmentation fault from multiple files using GDB

I have been asked in an interview how can you debug segmentation fault in C program using GDB.
I told them we can compile our program with -g option so as it add debugging information to binary file and can read core dump file but then interviewer told me if he we have 3 to 4 files compiled together but one of them causing segmentation fault then how do we debug in GDB?
$ gcc -ggdb s1.c s2.c s3.c -o myprog
$ gdb myprog
(gdb) run --arg1 --arg2
GDB will run the program as normal, when the segmentation fault occurs GDB will drop back to its prompt and it will be almost the same as running GDB with a core file. The major difference is there are some things you cannot do/print with a core file that you can when the program has crashed inside of GDB. (You can use print to call some functions inside the program, for example.)
You can also attach to an already running program using gdb --pid <the programs pid>.
Either with a core file or with one of the methods above, when you have the GDB prompt after the crash, type backtrace (or bt for short) and GDB will show you the stack at the time of the crash, including the file names and line numbers of each call and the currently executing line.
If you are working under Linux the easier way to find segmentation fault is by using the tool named VALGRIND: http://valgrind.org/ .
You just need to compile your code with -g flag and then run ./valgrind .
Then you will know exactly in which function and in which line of code there is an error-uninitialized memory/memory read out of allocated space or sth.
You just run the program under gdb, and the debugger with catch the SIGSEGV and show you the line and instruction that faulted. Then you just examine the variable and/or register values to see what's wrong. Usually it's a rogue pointer value, and trying to access it with GDB will give and error, so it's easy.
And yes, recompiling everything with -g would be helpful. The interviewer probably wanted you to describe how you'd figure out which file had the fault (gdb just tells you when it catches the signal) and just recompile that one with debug info. If there's 20,000 source files that might be useful, but with 3 or 4 files, what's the point? Even with larger projects, you usually end up chasing the bad pointer through 10 functions and 5 files anyway, so again, what's the point? Debug info doesn't cost anything at run time, although it costs disk space in an installation.
compile the code in normal way by giving gcc filename
you will get a .out file, start running that and get the process id by giving ps -aef | grep filename.out
in a another window type gdb and enter,inside gdb prompt give attach processid (processid you will get from above command),give c to continue.once the execution finishes give "bt" inside gdb.you will get the place where the segmentation is occurring.
Sounds like they are looking to set it up so that you can step through the code as it is running, you can do this with the command line version or I think you can get a GUI for GDB.
one can use the following steps to debug segmentation fault using gdb
$ gdb <exec name >
$ r //run the pgm
$ where
$ f <1> <0> //to view the function n variables
$ list
$ p <variable>

Why does GDB start a new shell and how to disable this behaviour?

I was figuring out a problem where starting the application from GDB results in a symbol lookup error, but starting it from the shell works.
It turns out that whenever you start a program from within GDB it will start a new shell and thus override all environment variables I had set before starting GDB (like LD_LIBRARY_PATH).
This is not really the behavior I want. Can someone explain the rationale behind this, or tell me how I can turn this off?
I am guessing that you unconditionally set LD_LIBRARY_PATH in your ~/.cshrc or the like. So if from a shell prompt you do this:
export LD_LIBRARY_PATH=foo # or for csh:
setenv LD_LIBRARY_PATH foo
$SHELL -c 'echo $LD_LIBRARY_PATH'
the result is something other than foo. Don't do that.
Usually this happens to CSH users, who neglected to protect their ~/.cshrc against non-interactive shells. It could also happen to BASH users who set their BASH_ENV.
I meet the same problem. I find that in inferior.h (source code of gdb gdb/inferior.h)
there is a macro STARTUP_WITH_SHELL, there is also a piece of comment as
/* If STARTUP_WITH_SHELL is set, GDB's "run"
will attempts to start up the debugee under a shell.
This is in order for argument-expansion to occur. E.g.,
(gdb) run *
The "*" gets expanded by the shell into a list of files.
While this is a nice feature, it turns out to interact badly
with some of the catch-fork/catch-exec features we have added.
In particular, if the shell does any fork/exec's before
the exec of the target program, that can confuse GDB.
To disable this feature, set STARTUP_WITH_SHELL to 0.
To enable this feature, set STARTUP_WITH_SHELL to 1.
The catch-exec traps expected during start-up will
be 1 if target is not started up with a shell, 2 if it is.
- RT
If you disable this, you need to decrement
START_INFERIOR_TRAPS_EXPECTED in tm.h. */
#define STARTUP_WITH_SHELL 1
#if !defined(START_INFERIOR_TRAPS_EXPECTED)
#define START_INFERIOR_TRAPS_EXPECTED 2
#endif
Then I set STARTUP_WITH_SHELL as 0 and decremented START_INFERIOR_TRAPS_EXPECTED
and recompiled my gdb. After that gdb didn't start from shell any more.
When you start gdb from the shell, you start it as a new process, there's no way around that. In Unix new processes inherit some of the environment of the parent.
To make sure a variable is inherited, if you're using a bourne-like shell, try exporting it:
export LD_LIBRARY_PATH=...
The debuggee (inferior in gdb parlance) is always started with a clean environment in order to get more reproducible results. In order to set a variable there, use the
set env VARNAME=VALUE
command before running.

Resources