I am getting some issues while following child process in dbx in a huge legacy C code. I am presenting below the code part under investigation:
#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
int main()
{
if(fork()) exit(0);
return 0;
}
when I run through dbx in Solaris 10, I am getting the following output:
Running: a.out
(process id 28193)
stopped in main at line 5 in file "a.c"
5 if(fork()) exit(0);
(dbx) next
dbx: detected a fork(). Do you want to follow parent, child or stop to investigate?
> child
Following child ...
detaching from process 28193
Attached to process 28197
stopped in __fork1 at 0xfeefc6b7
0xfeefc6b7: __fork1+0x0007: jb __cerror [ 0xfee70a40, .-0x8bc77 ]
Current function is main
5 if(fork()) exit(0);
dbx: warning: stepping up to a function with srcline info
Why I am getting this warning dbx: warning: stepping up to a function with srcline info?
Can anyone please help me over this? I am stuck at this point.
The function which dbx is trying to trace is __fork1(), which is provided
to you by libc. Oracle doesn't ship libc built with -g, which is what you
need in order to have source-line information in the debugger.
Related
We're learning to use GDB in my Computer Architecture class. To do this we do most of our work by using SSH to connect to a raspberry pi. When running GDB on some code he gave us to debug though it ends with an error message on how it can't find raise.c
I've tried:
installing libc6, libc6-dbg (says they're already up-to-date)
apt-get source glibc (gives me: "You must put some 'source' URIs in your sources.list")
https://stackoverflow.com/a/48287761/12015458 (apt source returns same thing as the apt-get source above, the "find $PWD" command the user gave returns nothing)
I've tried looking for it manually where told it may be? (/lib/libc doesn't exist for me)
This is the code he gave us to try debugging on GDB:
#include <stdio.h>
main()
{
int x,y;
y=54389;
for (x=10; x>=0; x--)
y=y/x;
printf("%d\n",y);
}
However, whenever I run the code in GDB I get the following error:
Program received signal SIGFPE, Arithmetic exception.
__GI_raise (sig=8) at ../sysdeps/unix/sysv/linux/raise.c:50
50 ../sysdeps/unix/sysv/linux/raise.c: No such file or directory.
I asked him about it and he didn't really have any ideas on how to fix it.
It does not really matter that the source for raise() is not found. It would only show you the line where the exception is finally raised, but not the place where the error is triggered.
Run the erroneous program again in GDB. And when the exception is raised, investigate the call stack and the stackframes with GBDs commands. This is the point in your task, so I won't give you more than this hint.
If you're clever you can see the error in the given source just by looking at it. ;-)
When GDB does not know any symbol, you need to compile with the option -g to get debugger support.
EDIT
Now on a Windows system this is my log (please excuse the colouring, I didn't found a language selector for pure text):
D:\tmp\StackOverflow\so_027 > type crash1.c
#include <stdio.h>
main()
{
int x,y;
y=54389;
for (x=10; x>=0; x--)
y=y/x;
printf("%d\n",y);
}
D:\tmp\StackOverflow\so_027 > gcc crash1.c -g -o crash1.out
crash1.c:2:1: warning: return type defaults to 'int' [-Wimplicit-int]
main()
^~~~
D:\tmp\StackOverflow\so_027 > dir
[...cut...]
04.09.2019 08:33 144 crash1.c
04.09.2019 08:40 54.716 crash1.out
D:\tmp\StackOverflow\so_027 > gdb crash1.out
GNU gdb (GDB) 8.1
[...cut...]
This GDB was configured as "x86_64-w64-mingw32".
[...cut...]
Reading symbols from crash1.out...done.
(gdb) run
Starting program: D:\tmp\StackOverflow\so_027\crash1.out
[New Thread 4520.0x28b8]
[New Thread 4520.0x33f0]
Thread 1 received signal SIGFPE, Arithmetic exception.
0x0000000000401571 in main () at crash1.c:7
7 y=y/x;
(gdb) backtrace
#0 0x0000000000401571 in main () at crash1.c:7
(gdb) help stack
Examining the stack.
The stack is made up of stack frames. Gdb assigns numbers to stack frames
counting from zero for the innermost (currently executing) frame.
At any time gdb identifies one frame as the "selected" frame.
Variable lookups are done with respect to the selected frame.
When the program being debugged stops, gdb selects the innermost frame.
The commands below can be used to select other frames by number or address.
List of commands:
backtrace -- Print backtrace of all stack frames
bt -- Print backtrace of all stack frames
down -- Select and print stack frame called by this one
frame -- Select and print a stack frame
return -- Make selected stack frame return to its caller
select-frame -- Select a stack frame without printing anything
up -- Select and print stack frame that called this one
Type "help" followed by command name for full documentation.
Type "apropos word" to search for commands related to "word".
Command name abbreviations are allowed if unambiguous.
(gdb) next
Thread 1 received signal SIGFPE, Arithmetic exception.
0x0000000000401571 in main () at crash1.c:7
7 y=y/x;
(gdb) next
[Inferior 1 (process 4520) exited with code 030000000224]
(gdb) next
The program is not being run.
(gdb) quit
D:\tmp\StackOverflow\so_027 >
Well, it marks directly the erroneous source line. That is different to your environment as you use a Raspi. However, it shows you some GDB commands to try.
Concerning your video:
It is clear that inside raise() you can't access x. That's why GDB moans about it.
If an exception is raised usually the program is about to quit. So there is no value in stepping forward.
Instead, as shown in my log, use GDB commands to investigate the stack frames. I think this is the issue you are about to learn.
BTW, do you know that you should be able to copy the screen content? This will make reading so much easier for us.
From a practical standpoint the other answer is correct, but if you do want the libc sources:
apt-get source is the right way to get the sources of libc, but yes, you do need to have source repositories configured in /etc/apt/sources.list.
If you're using Ubuntu, see the deb-src lines in https://help.ubuntu.com/community/Repositories/CommandLine
For debian, see https://wiki.debian.org/SourcesList#Example_sources.list
Then apt-get source should work. Remember to tell GDB where those sources are using the "directory" command.
Say with this simple code:
#include<stdio.h>
int main(int argc, char** argv){
printf("Hello World!\n");
return 0;
}
After stepping printf("Hello World!\n”); perhaps there’s a command to print that “Hellow World!\n” has been written to STDOUT.
And after return 0 perhaps there’s a command to see the exit codes generated and it will show 0.
Are there such commands or similar in lldb?
LLDB prints the exit status when a process exits:
(lldb) run
Process 76186 launched: '/tmp/a.out' (x86_64)
Process 76186 exited with status = 10 (0x0000000a)
and you can also access it with the SB API's:
(lldb) script lldb.process.GetExitStatus()
10
lldb doesn't have any special knowledge about all the ways a program might read or write data to a pipe, file handle, pty, etc... It also doesn't know how to interpose on file handles and tee-off the output. There's no particular reason it couldn't, but nobody has added that to date.
So you would have to build this yourself. If you know the API your code is using to read and write, you could use breakpoints to observe that - though that might get slow if you are observing a program that reads and writes a lot.
I am invoking make from my C program, which intern executes another program. I am redirecting both the standard out and standard error to a file. However, when the program run by make terminates due to segmentation fault, a core dump is generated and printed to the console (standard out) of the main program that is invoking make.
How can I get around this and not have the core dump show on the console?
The following is my code to invoke make :
int pid = fork();
if(pid==0){
dup2(make_logs, 1);
dup2(make_logs, 2);
close(make_logs);
execvp (args[0],args);
}
Where make_logs is the file opened using 'open'
Thanks
I would try to fix the core dump rather than suppressing the message, but the message about the segmentation fault is being generated by the shell (which detects the exit value of the child and recognize a core dump situation), so you can suppress it by installing your own program that handles the fork() and wait() rather than having the shell do the work.
To suppress the core dump, just use limit coredumpsize 0.
Sample of suppression (sloppy code; you should really be checking for errors):
#include <sys/types.h>
#include <sys/wait.h>
main( int argc, char **argv )
{
int pid;
if( (pid = fork() ) > 0 ) wait( 0 );
else if( pid == 0 ) {
execl( "program-that-cdumps", "program-that-cdumps", 0 );
perror("failed in execl");
} else perror("failed in fork");
}
Read core(5) and signal(7) man pages.
Compile all your programs with gcc -Wall -g. Then use
file core
to understand which binary dumped the core. It probably says something like core dump from foo to tell you that program foo dumped the core. Then, start a post mortem debugger on it:
gdb foo core
and use the common gdb commands (notably bt to backtrace, p to print, etc...).
The message dumped core is given by some shell (or perhaps by make when it is acting like a shell). I don't think that the core file is output to stdout (it is a big binary file).
If you wish to avoid the core (which IMHO is a bad idea, a core dump is a good symptom of something wrong), you could call the setrlimit(2) syscall with RLIMIT_CORE and a 0 limit after your fork and before the execvp. I believe you should not do that (or at least have some way of configuring that setrlimit is not called: sometimes you really need the core dump to debug the problem).
You should fix the problem which gives the core dump, not try to avoid the dumped core message!
If you run make on a user provided Makefile so that the core dump is from a user program, you really want to keep the user informed that a core did happen, so you should keep the core dumped message.
The concerned code is very huge and hence i am sorry i cannot post it here. The issue is:- I wrote a small program as follows:
#include<stdio.h>
#include<sys/types.h>
#include<unistd.h>
#include<signal.h>
int main()
{
printf("\n Process id",getpid());
fflush(stdout);
if(kill(getpid(),SIGSTOP)!=0)
printf("\nError");
}
Upon running i get the following o/p:
Process id 2664
[1]+ stopped ./test_SIGSTOP
[Directory Path]$
Which is exactly what is expected. But in my actual program which i said is very huge...control comes to just above the kill call(I know it as I have print statements and fflushed them) and hangs without automatically stopping the process and appearence of the command prompt.
Would be gratefull for pointers.
Thank
You can attach a debugger to a running program and find out where/why it hangs. Also, the raise() function is more convenient to use. But first, use ps and inspect the process's flags to confirm its status (running / sleeping / stopped).
This question already has answers here:
How can I see the output of an OS X program being run via the Time Profiler in Instruments?
(2 answers)
Closed 3 months ago.
I'm using Xcode on OSX to develop command line C applications. I would also like to use Instruments to profile and find memory leaks.
However, I couldn't find a way to display the console when launching the application from within Instruments. I'm also unable to attach to a running command line process (it exits with an error):
Here's an example code:
#include <stdio.h>
#include <signal.h>
#include <stdlib.h>
#include <setjmp.h>
static sigjmp_buf jmpbuf;
void handler(int sig) {
char c[BUFSIZ];
printf ("Got signal %d\n", sig);
printf ("Deseja sair? (s/n) ");
fgets(c, sizeof(c), stdin);
if(c[0] == 's') {
exit(0);
} else {
siglongjmp(jmpbuf, 1);
}
}
int main(void) {
char buf[BUFSIZ];
signal(SIGINT, handler);
sigsetjmp(jmpbuf, 1);
while(1) {
printf(">>>");
fgets(buf, sizeof(buf), stdin);
printf ("Introduziu: %s\n", buf);
}
return(0);
}
Here's the error I got after launching Instruments, and trying to attach to the running process in xcode:
[Switching to process 1475]
[Switching to process 1475]
Error while running hook_stop:
sharedlibrary apply-load-rules all
Error while running hook_stop:
Invalid type combination in ordering comparison.
Error while running hook_stop:
Invalid type combination in ordering comparison.
Error while running hook_stop:
Error while running hook_stop:
Error while running hook_stop:
Error while running hook_stop:
Error while running hook_stop:
Error while running hook_stop:
Error while running hook_stop:
Unable to disassemble __CFInitialize.
Any thoughts?
It's easy. See the screenshot.
It's a little late to contribute to this old thread, however I have found the best way of profiling a command line utility is to use iprofiler (manpage). This allows data to be collected from the command line simply by adding this to the start of the command line:
iprofiler -leaks -d $HOME/tmp
(I have a private temporary directory at $HOME/tmp, so you might need to use /tmp or leave the -d command line option off altogether).
My test scripts automatically add that to the command line if $FINDLEAKS is defined (and will prepend valgrind if running under Linux).
This then generates a .dtps file (actually a directory) which can be loaded and anaylysed using Instruments.
If you are compiling using clang then simply add both -O3 and -g (clang doesn't support the -pg command line option).
You can change the output in the Options dropdown when choosing your target. The output will appear in the system Console (Applications/Utilities/Console).