GDB breakpoint when executing external program through system() - c

I have the function system() call a separate script that has already been compiled. But I'd like to be able to set a breakpoint in functions within THAT specific file.
So:
File A:
system("./fileB");
File B:
void main() {
/* etc */
}
I'd like to be able to set a breakpoint at main after the system command is called.
Any help would be appreciated!

Newer versions of GDB (7.1+) can debug multiple programs at once and can indeed support this:
run-program.c
#include <stdlib.h>
int main()
{
system("./program-i-want-to-debug");
return 0;
}
program-i-want-to-debug.c
#include <stdio.h>
int main()
{
printf("Hello, World\n");
return 0;
}
run-program.gdb
set detach-on-fork off
set target-async on
set pagination off
set non-stop on
add-inferior -exec program-i-want-to-debug
break program-i-want-to-debug.c:5
file run-program
run
inferior 3
backtrace
Sample session
$ gdb -q -x run-program.gdb
Added inferior 2
Breakpoint 1 at 0x400441: file program-i-want-to-debug.c, line 5.
[New process 20297]
process 20297 is executing new program: /usr/bin/bash
process 20297 is executing new program: /home/scottt/Dropbox/stackoverflow/program-i-want-to-debug
Reading symbols from /home/scottt/Dropbox/stackoverflow/program-i-want-to-debug...done.
Breakpoint 1, main () at program-i-want-to-debug.c:5
5 printf("Hello, World\n");
[Switching to inferior 3 [process 20297] (/home/scottt/Dropbox/stackoverflow/program-i-want-to-debug)]
[Switching to thread 2 (process 20297)]
#0 main () at program-i-want-to-debug.c:5
5 printf("Hello, World\n");
#0 main () at program-i-want-to-debug.c:5
Obviously you'd want to compile the programs with debug info (gcc -g).

Maybe I do not catch your point. It seems that starting gdb debug on File A and setting a breakpoint on "FileB:line of main" resolve your problem.

Related

Stepping with gdb acts weird when encounters malloc call

I have a simple test program, and I'm trying to get the execution flow (I need to know which source code lines are executed) through a GDB script which simply executes step until the end of execution. Now something weird happens: when the stepping reaches malloc function the next step seems to go directly to the end of execution.
The simple program is the following:
#include <stdlib.h>
#include<stdio.h>
int f();
void g(int);
int main(void)
{
int len = f();
g(len);
printf("Execution terminated\n");
return 0;
}
int f(){
int fvar;
fvar = 20;
int* farray = malloc(fvar);
printf("Malloc executed: %p\n", farray);
return fvar;
}
void g(int var){
int gvar=var;
for(int i=0;i<gvar;i++)
var--;
}
Once compiled with: gcc -O0 -g -o test test.c
I run the GDB script with gdb -x script, where script is:
set pagination off
set logging file gdb.log
set logging on
file test
break main
run
while ( 1 )
step
end
And what I get is:
Breakpoint 1 at 0x1189: file test.c, line 8.
Breakpoint 1, main () at test.c:8
8 {
9 int len = f();
f () at test.c:17
17 int f(){
19 fvar = 20;
20 int* farray = malloc(fvar);
Malloc executed: 0x5555555592a0
Execution terminated
[Inferior 1 (process 5017) exited normally]
script:9: Error in sourced command file:
The program is not being run.
As you can see printf statements that come after the malloc are actually executed but it seems like the script is not stepping anymore.
I tried to issue next command right after the malloc and it actually prints the next line of code so it behaves differently from step command but obviously I can't replace step with next in the script because it won't step into my functions such as f and g.
I also tried to comment the line which contains the call to malloc and running the script with this version of the code actually prints each instruction executed until the end. But obviously this is not a fix :D
The problem is that with your script you continue to do step after the program is finished, from where the error The program is not being run.
You can use the solution you want but the principal is breaking the loop before the program is terminated. One solution would be to replace the return 0; with an exit(0); and to replace the while (1) with a while ($pc! = &exit) for example or $__GI_exit. You may have a No register error, but you can avoid this error by adding a break exit before run command.
An other solution is to add a print $pc in the loop to see the last address visited before, and compare directly the $pc to this address that you are sure it will be visited after the printf to break the loop. The pribt can be deleted once the address found. The easiest way still to use exit function when it is possible.
with the exit modification in the code. And the script modification:
set pagination off
set logging file gdb.log
set logging on
file exec
break main
break exit
run
while ( $pc != &exit)
step
end
The result is :
101 in filedoalloc.c
Malloc executed: 0x555555756260
Execution terminated
Breakpoint 2, __GI_exit (status=0) at exit.c:139
139 exit.c: No such file or directory.
(gdb)
GNU gdb (Ubuntu 8.1-0ubuntu3.2) 8.1.0.20180409-git and gcc (Ubuntu 7.5.0-3ubuntu1~18.04) 7.5.0 was used for the example.

Trouble debugging functions in linked libraries with gdb

I'm doing a bit of reading about gdb, and I'm having trouble getting gdb (I'm running 7.11.1) to debug a function from a library.
The sample code used to learn about the debugger is quite simple:
#include <stdio.h>
#include <string.h>
int main() {
char str_a[20];
strcpy(str_a, "Hello, world!\n");
printf(str_a);
}
I compiled it with debugging symbols enabled, fired up GDB, and set some breakpoints:
(gdb) list
1 #include <stdio.h>
2 #include <string.h>
3
4 int main() {
5 char str_a[20];
6
7 strcpy(str_a, "Hello, world!\n");
8 printf(str_a);
9 }
(gdb) break 7
Breakpoint 1 at 0x4005ad: file char_array2.c, line 7.
(gdb) break strcpy
Function "strcpy" not defined.
Make breakpoint pending on future shared library load? (y or [n]) y
Breakpoint 2 (strcpy) pending.
(gdb) break 8
Breakpoint 3 at 0x4005cf: file char_array2.c, line 8.
(gdb) run
Starting program: /home/david/hacking_the_art_of_exploitation/Chapter_2/char_array2
Breakpoint 1, main () at char_array2.c:7
7 strcpy(str_a, "Hello, world!\n");
(gdb) continue
Continuing.
Breakpoint 3, main () at char_array2.c:8
8 printf(str_a);
(gdb) continue
Continuing.
Hello, world!
[Inferior 1 (process 7061) exited normally]
As you can see, the debugger never descends into the strcpy function.
I've tried adding set stop-on-solib-events 1 to my .gdbinit. This leads to different but still undesirable results:
(gdb) run
Starting program: /home/david/hacking_the_art_of_exploitation/Chapter_2/char_array2
Stopped due to shared library event (no libraries added or removed)
I'm at a bit of a loss here. Thanks in advance for any help.
I believe you need the libc-dbg package and the libc source package for debugging a libc function. On Ubuntu you can install it via
sudo apt-get install libc6-dbg
mkdir ~/libc ; cd ~/libc
apt-get source libc6

SDL simple threading produces segmentation fault

I've been trying to use SDL threading, but I've not been able to make it work properly. Even the simplest programs cause a segmentation fault.
I'm using mingw64 (not mingw32) inside the cygwin environment.
This code produces a segmentation fault both when run inside cygwin and outside it:
#include <SDL.h>
#include <SDL_thread.h>
int threadFunction(void* data) {
return 0;
}
int main(int argc,char* argv[]) {
int dataIn=0;
int dataOut=0;
SDL_Thread* thread;
SDL_Window* window;
SDL_Init(0);
thread=SDL_CreateThread(&threadFunction,"Thread",&dataIn);
SDL_WaitThread(thread,&dataOut);
SDL_Quit();
return 0;
}
However, once printf statements are added in between, like so:
SDL_Init(0);
printf("#1 ");
thread=SDL_CreateThread(&threadFunction,"Thread",&dataIn);
printf("#2 ");
SDL_WaitThread(thread,&dataOut);
printf("#3 ");
SDL_Quit();
printf("#4 ");
return 0;
Something very strange happens. When this code is run inside the cygwin environment, either with or without the -mwindows option, it works ok. The program exits normally. When this same code is run outside the cygwin environment it crashes only without the -mwindows option. Rearranging the printf's around has diverse results, sometimes making it crash and sometimes not.
When this code is run, the output is this:
Cygwin: ./test -> #1 #2 #3 #4
Windows: test -> #1 (program freezes and a "test.exe has stopped working" window appears)
The compilation command I'm using is this: gcc -I./SDL2 -o test test.c -lmingw32 -lSDL2main -lSDL2 where gcc is a symlink to the x86_64 version of the mingw64 C compiler. I've also tried with the normal x86 (i386, 32-bits) version of mingw64/SDL and the same thing happens.
When compiling with the -g option and using gdb on the first example (without printf's) this is shown:
Starting program: /Test/test
[New Thread 5828.0x1084]
Program received signal SIGSEGV, Segmentation fault.
0x000000006c868e30 in ?? () from /Test/SDL2.dll
(gdb) where
#0 0x000000006c868e30 in ?? () from /Test/SDL2.dll
#1 0x000000006c830d29 in SDL_LogCritical ()
from /Test/SDL2.dll
#2 0x000000006c7cb85f in SDL_LogCritical ()
from /Test/SDL2.dll
#3 0x0000000000401600 in SDL_main (argc=1, argv=0x2f0010) at test.c:17
#4 0x0000000000402cfa in console_main ()
#5 0x0000000000402db1 in WinMain ()
#6 0x00000000004013e8 in __tmainCRTStartup ()
at /usr/src/debug/mingw64-x86_64-runtime-4.0.6-1/crt/crtexe.c:332
#7 0x000000000040151b in mainCRTStartup ()
at /usr/src/debug/mingw64-x86_64-runtime-4.0.6-1/crt/crtexe.c:212
Whereas the printf version:
Starting program: /home/Mimi/Escocia/C/Test/test
[New Thread 3380.0x98c]
[New Thread 3380.0x1a80]
[Thread 3380.0x1a80 exited with code 0]
#1 #2 #3 #4 [Inferior 1 (process 3380) exited normally]
(But running this program outside cygwin produces a segfault)
Is linking with libmingw32 on mingw64 wrong? (It doesn't seem right either, but it didn't compile without it.) Am I missing something obvious? Does anybody know what I'm doing wrong? Is it a bug? (If it is, where should I report it to: SDL, mingw64 or Cygwin?)
Thanks in advance.
EDIT: After recompiling SDL the problem is gone. Does anyone know why does it work now? Are there any disadvantages to compiling it myself?

Gdbserver, remote debugging, printf() output not seen on the host

I am running gdbserver on a remote armv5 target with the following command line:
./gdbserver --debug --remote-debug --multi :9000
The host machine is x86 Linux. I am trying to remote-debug a sample hello_world.c program, pretty much a int main(int argc, char** argv) { printf("hello world\n"); exit(0); };
I am doing the following on the host machine:
./gdb
(gdb)set sysroot /home/username
(gdb)set verbose on
(gdb)target extended-remote 192.168.1.217:9000
(gdb)file hello_world
(gdb)set remote exec-file /upgrade/hello_world
(gdb)r
The output is as follows:
Starting program: /home/username/hello_world
Loaded symbols for /lib/ld-linux.3.so
Loaded symbols for /lib/libc.6.so
Breakpoint 1, main (argc=1, argv=0xbe90cdd4) at hello_world.c:50
50 int parm=7;
(gdb) c
Continuing.
[Inferior 1 (process 16721) exited normally]
Notice that there is no printf() output on the host machine. It just stops on a breakpoint and then runs to completion when I hit 'c'.
I expect the \n in the printf to flush the buffer and produce output immediately, but for some reason I do not see it in the host gdb window.
Any thoughts ?

How to debug the entry-point of fork-exec process in GDB?

I have a C linux application (A) that spawns another process (P) when it is started. When I want to debug P I start A as usual and I connect with ddd/gdb to P.
Problems appear when I want to debug the entry-point (start of main) of P. If I follow the usual approach when I connect the debugger to P is already to late. The solution I've found was to insert a sleep at the begining of the main of P so I have time to connect with gdb but this is not a very elegant solution.
I've also tried using asm("int $3") but it doesn't seems to work.
Do you have any idea how I could solve this problem? (preferably without altering the code of A or P)
You should use this option:
set follow-fork-mode mode
Where mode is one of parent, child or ask.
To follow the parent (this is the default) use:
set follow-fork-mode parent
To follow the child:
set follow-fork-mode child
To have the debugger ask you each time:
set follow-fork-mode ask
So basically you'd start out connecting gdb to A, then set gdb to follow the child, and then when A spawns P, gdb will connect to P and detach from A.
In addition to the Nathan Fellman's answer, catchpoints come in handy, i.g.:
catch exec
Catchpoint works as a breakpoint. Every time a call to exec() syscall is detected, GDB stops. This allows you to set any breakpoint (i.g. break main) in any newly loaded executable before continuing. Another catchpoint catch fork works similarly for fork() syscall detection.
It is especially convenient:
when both parent and child has to be followed (set detach-on-fork off);
when parent processes forks often loading various executables.
exec part with file + break main
The fork was part was explained at: https://stackoverflow.com/a/377295/895245
Now for the exec:
a.c:
#include <unistd.h>
int main(void) {
execl("./b", "./b", "ab", "cd", (char*)NULL);
return 1;
}
b.c:
#include <stdio.h>
int main(int argc, char **argv ) {
printf("%s\n", argv[0]);
printf("%s\n", argv[1]);
}
Then:
gcc -g a.c -o a
gcc -g b.c -o b
gdb -nh -q a
Now on the interactive session:
Reading symbols from a...done.
(gdb) start
Temporary breakpoint 1 at 0x4004ea: file a.c, line 4.
Starting program: /home/ciro/test/gdb-exec/a
Temporary breakpoint 1, main () at a.c:4
4 execl("./b", "./b", "ab", "cd", (char*)NULL);
(gdb) file b
A program is being debugged already.
Are you sure you want to change the file? (y or n) y
Load new symbol table from "b"? (y or n) y
Reading symbols from b...done.
(gdb) b main
Breakpoint 2 at 0x4004f5: file b.c, line 4.
(gdb) n
Breakpoint 2, main (argc=0, argv=0x7fffffffa570) at b.c:4
4 printf("%s\n", argv[1]);
(gdb) n
process 4877 is executing new program: /home/ciro/test/gdb-exec/b
Breakpoint 2, main (argc=3, argv=0x7fffffffa598) at b.c:4
4 printf("%s\n", argv[1]);
(gdb) n
ab
5 printf("%s\n", argv[2]);
(gdb) n
cd
6 }
(gdb)
You just have to make sure that you go up to the exec before running file, possibly with a b execl, since after that you will be using symbols from the new file.
Tested in Ubuntu 14.04, gdb 7.7.1.
You should be able to do this by making use of gdb's remote debugging features, specifically gdbserver. In effect, launch (P) using gdbserver. These links have more detailed info:
Using gdbserver
GDB Remote Debugging
set a break point at main(), it will also break at main() of the execed program.

Resources