How to "unwind" a core dump in gdb - c

I'm not sure if this is the correct wording of the issue, but let's take the following example where I have a program that will crash/abort:
#include <assert.h>
int main(void)
{
int z=2;
assert (z>5);
}
And if I compile it with debugging and then run it:
$ gcc -ggdb3 a.c -o a.o && ./a.o
a.o: a.c:8: main: Assertion `z>5' failed.
Aborted (core dumped)
Now I'll open it up in gdb to see if I can inspect the program:
$ gdb a.o core
Core was generated by `./a.o'.
Program terminated with signal SIGABRT, Aborted.
#0 __GI_raise (sig=sig#entry=6) at ../sysdeps/unix/sysv/linux/raise.c:51
51 ../sysdeps/unix/sysv/linux/raise.c: No such file or directory.
If I now "run" the program with r I will get something like this (from gdb-dashboard viewer):
My question is the stack is now pretty deep into the C runtime / linux:
─── Stack ──────────────────────────────────────────────────────────────────────────────────────────
[0] from 0x00007ffff7a22f47 in __GI_raise+199 at ../sysdeps/unix/sysv/linux/raise.c:51
[1] from 0x00007ffff7a248b1 in __GI_abort+321 at abort.c:79
[2] from 0x00007ffff7a1442a in __assert_fail_base+330 at assert.c:92
[3] from 0x00007ffff7a144a2 in __GI___assert_fail+66 at assert.c:101
[4] from 0x00005555555546ce in main+52 at a.c:8
Is it possible that I can unwind the stack to where the error was triggered:
[4] from 0x00005555555546ce in main+52 at a.c:8
So that I can see what the registers, variables, etc. were at that point? Another way to phrase the question is "How do I ignore things outside my code when inspecting a core dump / gdb" ?

Here's a stab at this:
To travel up or down the callstack, use up|down. In this case we do up 4 to get back to main:
>>> up 4
#4 0x000055555555467e in main () at a.c:7
7 assert (z>5);
info frame and info locals can tell us high-level information about the function:
>>> info locals
z = 2
__PRETTY_FUNCTION__ = "main"
>>> info frame
Stack level 4, frame at 0x7fffffffe0e0:
rip = 0x55555555467e in main (a.c:7); saved rip = 0x7ffff7a05b97
caller of frame at 0x7fffffffe0c0
source language c.
Arglist at 0x7fffffffe0d0, args:
Locals at 0x7fffffffe0d0, Previous frame's sp is 0x7fffffffe0e0
Saved registers:
rbp at 0x7fffffffe0d0, rip at 0x7fffffffe0d8
For example, given the above, we can make a guess that the un-optimized assembly would put z into %rbp-4 and we can examine its value there:
>>> x/d $rbp-4
0x7fffffffe0cc: 2
# or, in long-form to ensure our rbp address above from `info` is the same:
>>> x/d 0x7fffffffe0d0-4
0x7fffffffe0cc: 2

Related

Watchpoint doesn't work when reverse executing

Here's a debugging scenario:
Create start breakpoint A and finish breakpoint B.
Start recording. Continue.
Reach breakpoint B.
Set watchpoint to watch writes to some piece of memory.
Reverse continue until watchpoint breaks execution.
Let's suppose that setting the watchpoint is only possible in step 4, not earlier, since the location of memory that should be watched is only known at that point.
Here's a simple example.
main.c:
int main(void)
{
int num;
num = 5;
return 0;
}
Debugging session:
$ cc main.c
$ gdb -q -nx -ex 'set disassembly-flavor intel' ./a.out
Reading symbols from ./a.out...
(No debugging symbols found in ./a.out)
(gdb) b *main + 0
Breakpoint 1 at 0x1129
(gdb) disas main
Dump of assembler code for function main:
0x0000000000001129 <+0>: push rbp
0x000000000000112a <+1>: mov rbp,rsp
0x000000000000112d <+4>: mov DWORD PTR [rbp-0x4],0x5
0x0000000000001134 <+11>: mov eax,0x0
0x0000000000001139 <+16>: pop rbp
0x000000000000113a <+17>: ret
End of assembler dump.
(gdb) b *main + 16
Breakpoint 2 at 0x1139
(gdb) r
Starting program: /var/tmp/test/a.out
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".
Breakpoint 1, 0x0000555555555129 in main ()
(gdb) record
(gdb) c
Continuing.
Breakpoint 2, 0x0000555555555139 in main ()
(gdb) p/x $rbp-0x4
$1 = 0x7fffffffe63c
(gdb) watch *(int*)0x7fffffffe63c
Hardware watchpoint 3: *(int*)0x7fffffffe63c
(gdb) reverse-continue
Continuing.
No more reverse-execution history.
0x0000555555555129 in main ()
(gdb)
The last command shows that reverse execution didn't stop where it is supposed to stop, that is *main+4. Instead, it stopped where the recording has started, ignoring any memory writes.
My simple experiment was motivated by that video at the CppCon 2015, highlighting usefulness of the record & replay concept. Really, I don't know what I've done wrong, because for me it seems that I've repeated every step from the video.
Also, reading gdb docs didn't help either.
So, why the watchpoint has been ignored and how can it be prevented?
Try telling gdb to use a software breakpoint instead of the hardware one through the command set can-use-hw-watchpoints 0.
It seems that the hardware watchpoint doesn't work here because when executing back and forth through reverse-execution history, no traditional process execution takes place, it's only gdb changing it's internal memory to make appearance that a program executed backwards.
In other words, we should use hardware watchpoints when the real process executes on a CPU, and software watchpoints when gdb makes an emulation through its recording history.
Thanks to Peter Cordes for the explanation in the comments.

Overwriting the stored return address on the stack doesn't work

I'm trying to take control of a C program's execution by overwriting the stored return address (saved eip) on the stack:
(gdb) info frame
Stack level 0, frame at 0xbffff550:
eip = 0x8048831 in main (6.c:52); saved eip = 0xbffffdef
source language c.
Arglist at 0xbffff538, args: argc=6, argv=0xbffff5e4
Locals at 0xbffff538, Previous frame's sp is 0xbffff550
Saved registers:
ebx at 0xbffff534, ebp at 0xbffff538, eip at 0xbffff54c
The value 0xbffffdef is the address of a "Hello, world!" shellcode which has been assembled, checked for any null bytes and put in an environment variable SHELLCODE:
(gdb) x/s *((char **)environ + 7)
0xbffffdef: "SHELLCODE=\353\023Y1\300\260\004\061\333C1Ҳ\017̀\260\001K̀\350\350\377\377\377Hello, world!\n\r"
Unfortunately the program fails to print the expected greeting:
Program received signal SIGSEGV, Segmentation fault.
0xbffffdfd in ?? ()
Why did it crash and how to solve the problem?
Notes:
gcc (Ubuntu 7.5.0-3ubuntu1~18.04) 7.5.0
GNU gdb (Ubuntu 8.1-0ubuntu3.2) 8.1.0.20180409-git
// program was compiled with the following flags:
-m32 -fno-stack-protector -z execstack -fno-PIE -no-pie -g
program source: link
Credits to #Nate Eldredge
The reason behind this specific crash is the incorrect return address 0xbffffdef. The location of the environment variable SHELLCODE actually points to the beginning of the string "SHELLCODE=..."
(gdb) x/s *((char **)environ + 7)
0xbffffdef: "SHELLCODE=\353\023Y1\300\260\004\061\333C1Ҳ\017̀\260\001K̀\350\350\377\377\377Hello, world!\n\r"
In order to fix the issue, we have to adjust the address by skipping the first 10 characters and point to the "\353\023Y1\300...":
0xbffffdef + 0xa = 0xbffffdf9
When overwriting the stored return address with this value 0xbffffdf9, the program is coerced into greeting the world:
(gdb) info frame
Stack level 0, frame at 0xbffff550:
eip = 0x8048831 in main (6.c:52); saved eip = 0xbffffdf9
source language c.
Arglist at 0xbffff538, args: argc=6, argv=0xbffff5e4
Locals at 0xbffff538, Previous frame's sp is 0xbffff550
Saved registers:
ebx at 0xbffff534, ebp at 0xbffff538, eip at 0xbffff54c
(gdb) cont
Continuing.
Hello, world!
[Inferior 1 (process 28591) exited normally]

Why is it that gdb "can't compute CFA" when using a separate debug symbols file?

I'm trying to invoke gdb with a stripped executable and a separate debug symbols file, on a core dump generated from running the stripped executable.
But when I use the separate debug symbols file, gdb is unable to give information on local variables for me.
Here is a log showing entirely how I produce my 3 ELF files and the core file and then run them through gdb 3 times.
First I just run gdb with the stripped executable and of course can't see any file names or line numbers, and can't inspect variables.
Then I run gdb using the stripped executable and grabbing the debug symbols from the original unstripped executable. This works pretty well but does give a disturbing and apparently unwarranted warning about the core and executable possibly mismatching.
Finally I run gdb with the stripped executable and the separate debug file. This still gives filenames and line numbers, but I can't inspect local variables and I get a "can't compute CFA for this frame" error.
Here is the log:
2016-09-16 16:01:45 barry#somehost ~/proj/segfault/segfault
$ cat segfault.c
#include <stdio.h>
int main(int argc, char **argv) {
char *badpointer = (char *)0x2398723;
printf("badpointer: %s\n", badpointer);
return 0;
}
2016-09-16 16:03:31 barry#somehost ~/proj/segfault/segfault
$ gcc -g -o segfault segfault.c
2016-09-16 16:03:37 barry#somehost ~/proj/segfault/segfault
$ objcopy --strip-debug segfault segfault.stripped
2016-09-16 16:03:40 barry#somehost ~/proj/segfault/segfault
$ objcopy --only-keep-debug segfault segfault.debug
2016-09-16 16:03:43 barry#somehost ~/proj/segfault/segfault
$ ./segfault.stripped
Segmentation fault (core dumped)
2016-09-16 16:03:48 barry#somehost ~/proj/segfault/segfault
$ ll /tmp/core.segfault.stripp.11
-rw------- 1 barry bsm-it 188416 2016-09-16 16:03 /tmp/core.segfault.stripp.11
2016-09-16 16:03:51 barry#somehost ~/proj/segfault/segfault
$ gdb ./segfault.stripped /tmp/core.segfault.stripp.11
GNU gdb (GDB) Fedora (7.0.1-50.fc12)
Copyright (C) 2009 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law. Type "show copying"
and "show warranty" for details.
This GDB was configured as "x86_64-redhat-linux-gnu".
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>...
Reading symbols from /home/barry/proj/segfault/segfault/segfault.stripped...(no debugging symbols found)...done.
warning: core file may not match specified executable file.
Missing separate debuginfo for
Try: yum --disablerepo='*' --enablerepo='*-debuginfo' install /usr/lib/debug/.build-id/a6/8dce9115a92508af92ac4ccac24b9f0cc34d71
Reading symbols from /lib64/libc.so.6...(no debugging symbols found)...done.
Loaded symbols for /lib64/libc.so.6
Reading symbols from /lib64/ld-linux-x86-64.so.2...(no debugging symbols found)...done.
Loaded symbols for /lib64/ld-linux-x86-64.so.2
Core was generated by `./segfault.stripped'.
Program terminated with signal 11, Segmentation fault.
#0 0x00000035fec47cb7 in vfprintf () from /lib64/libc.so.6
Missing separate debuginfos, use: debuginfo-install glibc-2.11.2-3.x86_64
(gdb) bt
#0 0x00000035fec47cb7 in vfprintf () from /lib64/libc.so.6
#1 0x00000035fec4ec4a in printf () from /lib64/libc.so.6
#2 0x00000000004004f4 in main ()
(gdb) up
#1 0x00000035fec4ec4a in printf () from /lib64/libc.so.6
(gdb) up
#2 0x00000000004004f4 in main ()
(gdb) p argc
No symbol table is loaded. Use the "file" command.
(gdb) q
2016-09-16 16:04:19 barry#somehost ~/proj/segfault/segfault
$ gdb -q -e ./segfault.stripped -s ./segfault -c /tmp/core.segfault.stripp.11
Reading symbols from /home/barry/proj/segfault/segfault/segfault...done.
warning: core file may not match specified executable file.
Missing separate debuginfo for
Try: yum --disablerepo='*' --enablerepo='*-debuginfo' install /usr/lib/debug/.build-id/a6/8dce9115a92508af92ac4ccac24b9f0cc34d71
Reading symbols from /lib64/libc.so.6...(no debugging symbols found)...done.
Loaded symbols for /lib64/libc.so.6
Reading symbols from /lib64/ld-linux-x86-64.so.2...(no debugging symbols found)...done.
Loaded symbols for /lib64/ld-linux-x86-64.so.2
Core was generated by `./segfault.stripped'.
Program terminated with signal 11, Segmentation fault.
#0 0x00000035fec47cb7 in vfprintf () from /lib64/libc.so.6
Missing separate debuginfos, use: debuginfo-install glibc-2.11.2-3.x86_64
(gdb) bt
#0 0x00000035fec47cb7 in vfprintf () from /lib64/libc.so.6
#1 0x00000035fec4ec4a in printf () from /lib64/libc.so.6
#2 0x00000000004004f4 in main (argc=1, argv=0x7fffd1c0a728) at segfault.c:4
(gdb) up
#1 0x00000035fec4ec4a in printf () from /lib64/libc.so.6
(gdb) up
#2 0x00000000004004f4 in main (argc=1, argv=0x7fffd1c0a728) at segfault.c:4
4 printf("badpointer: %s\n", badpointer);
(gdb) p argc
$1 = 1
(gdb) q
2016-09-16 16:04:39 barry#somehost ~/proj/segfault/segfault
$ gdb -q -e ./segfault.stripped -s ./segfault.debug -c /tmp/core.segfault.stripp.11
Reading symbols from /home/barry/proj/segfault/segfault/segfault.debug...done.
warning: core file may not match specified executable file.
Missing separate debuginfo for
Try: yum --disablerepo='*' --enablerepo='*-debuginfo' install /usr/lib/debug/.build-id/a6/8dce9115a92508af92ac4ccac24b9f0cc34d71
Reading symbols from /lib64/libc.so.6...(no debugging symbols found)...done.
Loaded symbols for /lib64/libc.so.6
Reading symbols from /lib64/ld-linux-x86-64.so.2...(no debugging symbols found)...done.
Loaded symbols for /lib64/ld-linux-x86-64.so.2
Core was generated by `./segfault.stripped'.
Program terminated with signal 11, Segmentation fault.
#0 0x00000035fec47cb7 in vfprintf () from /lib64/libc.so.6
Missing separate debuginfos, use: debuginfo-install glibc-2.11.2-3.x86_64
(gdb) bt
#0 0x00000035fec47cb7 in vfprintf () from /lib64/libc.so.6
#1 0x00000035fec4ec4a in printf () from /lib64/libc.so.6
#2 0x00000000004004f4 in main (argc=can't compute CFA for this frame
) at segfault.c:4
(gdb) up
#1 0x00000035fec4ec4a in printf () from /lib64/libc.so.6
(gdb) up
#2 0x00000000004004f4 in main (argc=can't compute CFA for this frame
) at segfault.c:4
4 printf("badpointer: %s\n", badpointer);
(gdb) p argc
can't compute CFA for this frame
(gdb) q
I have some questions about this:
Why does it display the warning "warning: core file may not match specified executable file.", even though I'm using the exact same executable path as was used when the core dump was originally generated?
Why does using the separate debug symbols (-s ./segfault.debug) result in the error "can't compute CFA for this frame" when attempting to inspect local variables?
What is a CFA anyway?
Am I using an incorrect method to product the debug symbol file?
I confirmed that using "objcopy --strip-debug" gives the same result as "strip -g".
Am I using the right options to feed the debug info into gdb?
My intention is that the stripped executables will be installed on a binary-compatible production system and any core dumps generated due to segfaults can be copied back to the devel system where we can feed them into gdb with the debug info and analyse the crash position and stack variables. But as a first step I'm trying to sort out the issues with using separate debug info files on the devel system.
It seems that using a separate debug symbols file causes the "can't compute CFA for this frame" error, even when a core file is not used.
My gcc version:
2016-09-16 16:07:39 barry#somehost ~/proj/segfault/segfault
$ gcc -v
Using built-in specs.
Target: x86_64-redhat-linux
Configured with: ../configure --prefix=/usr --mandir=/usr/share/man --infodir=/usr/share/info --with-bugurl=http://bugzilla.redhat.com/bugzilla --enable-bootstrap --enable-shared --enable-threads=posix --enable-checking=release --with-system-zlib --enable-__cxa_atexit --disable-libunwind-exceptions --enable-gnu-unique-object --enable-languages=c,c++,objc,obj-c++,java,fortran,ada --enable-java-awt=gtk --disable-dssi --enable-plugin --with-java-home=/usr/lib/jvm/java-1.5.0-gcj-1.5.0.0/jre --enable-libgcj-multifile --enable-java-maintainer-mode --with-ecj-jar=/usr/share/java/eclipse-ecj.jar --disable-libjava-multilib --with-ppl --with-cloog --with-tune=generic --with-arch_32=i686 --build=x86_64-redhat-linux
Thread model: posix
gcc version 4.4.4 20100630 (Red Hat 4.4.4-10) (GCC)
I suspect that gdb might be looking for symbols related to the variables in the segfault.debug file when objcopy actually only put them in the segfault.stripped file. If this is the case, perhaps some small adjustment to the options to objcopy could put those symbols in the place gdb is looking?
I commend you for wanting to keep a set of symbol files for everything that is deployed to the production server; in my opinion this is an often overlooked practice, but you will not regret it -- one day it will save you a lot of debugging trouble.
As I have had similar issues in the past, I will try to answer some of your questions, although you have quite an ancient toolchain, if you don't mind me saying so, so I'm not sure how much that really applies here. I'll put up here anyway.
CFA = Canonical Frame Address. This is the base pointer to the stack frame that every local variable is addressed relative to. If you have done some traditional x86 assembly programming, the BP register was used for this. So "can't compute CFA for this frame" basically says "I know of these local variables, but I don't know where they are located on the stack".
There used to be code in GDB that worked only for the DWARF-2 debugging format, and non-conformance triggered this particular error at least. That restriction was lifted some time ago, but that change won't be in your version.
The other thing is there are debug information regarding how variables may be moved around is not always generated. This usually happens in newer compilers though, as they get better at optimizing.
I was able to get rid of my problems by compiling like this:
gcc -g3 -gdwarf-2 -fvar-tracking -fvar-tracking-assignments -o segfault segfault.c
you can try to see if this solves your problem, too.
Regarding the message about the location of the symbol file; it seems that the debugger wants to load it from the system directory. Maybe you have to link the executable to the symbol file with:
objcopy --add-gnu-debuglink=segfault.debug segfault
I found this question while searching for an answer to the following part of the original question:
Why does it display the warning "warning: core file may not match
specified executable file.", even though I'm using the exact same
executable path as was used when the core dump was originally
generated?
There was not an answer to this particular question but through experimentation and research I believe I have found the answer.
Below is a transcript of using gdb to debug a core file. Notice that the "warning: core file may not match specified executable file." error appears when the executable file that caused the core is greater than 15 characters in length.
[~/t]$cat do_abort.c
#include <stdlib.h>
int func4(int f) { if(f) {abort();} return 0;}
int func3(int f) { return func4(f); }
int func2(int f) { return func3(f); }
int func1(int f) { return func2(f); }
int main(void) { return func1(1); }
[~/t]$gcc -g -o 123456789012345 do_abort.c
[~/t]$./123456789012345
Aborted (core dumped)
[~/t]$ll core*
-rw-------. 1 dev wheel 240K Apr 22 03:19 core.42697
[~/t]$gdb -q -c core.42697 123456789012345
Reading symbols from /home/dev/t/123456789012345...done.
[New LWP 42697]
Core was generated by `./123456789012345'.
Program terminated with signal 6, Aborted.
#0 0x00007f0be67631d7 in __GI_raise (sig=sig#entry=6) at ../nptl/sysdeps/unix/sysv/linux/raise.c:56
56 return INLINE_SYSCALL (tgkill, 3, pid, selftid, sig);
(gdb) bt
#0 0x00007f0be67631d7 in __GI_raise (sig=sig#entry=6) at ../nptl/sysdeps/unix/sysv/linux/raise.c:56
#1 0x00007f0be67648c8 in __GI_abort () at abort.c:90
#2 0x0000000000400543 in func4 (f=1) at do_abort.c:3
#3 0x000000000040055f in func3 (f=1) at do_abort.c:4
#4 0x0000000000400576 in func2 (f=1) at do_abort.c:5
#5 0x000000000040058d in func1 (f=1) at do_abort.c:6
#6 0x000000000040059d in main () at do_abort.c:7
(gdb) quit
[~/t]$rm core.42697
[~/t]$
[~/t]$mv 123456789012345 1234567890123456
[~/t]$./1234567890123456
Aborted (core dumped)
[~/t]$ll core*
-rw-------. 1 dev wheel 240K Apr 22 03:20 core.42721
[~/t]$gdb -q -c core.42721 1234567890123456
Reading symbols from /home/dev/t/1234567890123456...done.
warning: core file may not match specified executable file.
[New LWP 42721]
Core was generated by `./1234567890123456'.
Program terminated with signal 6, Aborted.
#0 0x00007f5b271fa1d7 in __GI_raise (sig=sig#entry=6) at ../nptl/sysdeps/unix/sysv/linux/raise.c:56
56 return INLINE_SYSCALL (tgkill, 3, pid, selftid, sig);
(gdb) bt
#0 0x00007f5b271fa1d7 in __GI_raise (sig=sig#entry=6) at ../nptl/sysdeps/unix/sysv/linux/raise.c:56
#1 0x00007f5b271fb8c8 in __GI_abort () at abort.c:90
#2 0x0000000000400543 in func4 (f=1) at do_abort.c:3
#3 0x000000000040055f in func3 (f=1) at do_abort.c:4
#4 0x0000000000400576 in func2 (f=1) at do_abort.c:5
#5 0x000000000040058d in func1 (f=1) at do_abort.c:6
#6 0x000000000040059d in main () at do_abort.c:7
(gdb) quit
[~/t]$mv 1234567890123456 123456789012345
[~/t]$gdb -q -c core.42721 123456789012345
Reading symbols from /home/dev/t/123456789012345...done.
[New LWP 42721]
Core was generated by `./1234567890123456'.
Program terminated with signal 6, Aborted.
#0 0x00007f5b271fa1d7 in __GI_raise (sig=sig#entry=6) at ../nptl/sysdeps/unix/sysv/linux/raise.c:56
56 return INLINE_SYSCALL (tgkill, 3, pid, selftid, sig);
(gdb) bt
#0 0x00007f5b271fa1d7 in __GI_raise (sig=sig#entry=6) at ../nptl/sysdeps/unix/sysv/linux/raise.c:56
#1 0x00007f5b271fb8c8 in __GI_abort () at abort.c:90
#2 0x0000000000400543 in func4 (f=1) at do_abort.c:3
#3 0x000000000040055f in func3 (f=1) at do_abort.c:4
#4 0x0000000000400576 in func2 (f=1) at do_abort.c:5
#5 0x000000000040058d in func1 (f=1) at do_abort.c:6
#6 0x000000000040059d in main () at do_abort.c:7
(gdb) quit
Following through the gdb source code I discovered that the ELF core file structure only reserves sixteen bytes to hold the executable filename, pr_fname[16], including the nul terminator (reference):
35 struct elf_external_linux_prpsinfo32_ugid32
36 {
37 char pr_state; /* Numeric process state. */
38 char pr_sname; /* Char for pr_state. */
39 char pr_zomb; /* Zombie. */
40 char pr_nice; /* Nice val. */
41 char pr_flag[4]; /* Flags. */
42 char pr_uid[4];
43 char pr_gid[4];
44 char pr_pid[4];
45 char pr_ppid[4];
46 char pr_pgrp[4];
47 char pr_sid[4];
48 char pr_fname[16]; /* Filename of executable. */
49 char pr_psargs[80]; /* Initial part of arg list. */
50 };
The "warning: core file may not match specified executable file." warning will be issued by gdb when the name of the executable passed on the command-line to gdb doesn't match the value stored in pr_fname[] in the core file (references here, here, and here).
Using the demonstration I showed at the start of this answer, when the filename is 1234567890123456 the filename stored in the core file as pr_fname[] is 123456789012345 (truncated to 15 characters). If gdb is started using gdb -c core.XXXX 1234567890123456 then the warning will be issued. If gdb is started using gdb -c core.XXXX 123456789012345 then the warning will not be issued.
It should follow that in the example from the original question, if segfault.stripped was renamed to segfault.stripp and gdb was run using gdb ./segfault.stripp /tmp/core.segfault.stripp.11 then the warning should not be issued.

localtime() crashing with segmentation fault in c

Have a bit of trouble tracking down the cause of this.
Here is the code bit:
#include <time.h>
time_t now;
struct tm *mytime;
char yyyy[5];
char mm[3];
char dd[3];
char mname[10];
if(time(&now)!=(time_t)(-1))
{
mytime=localtime(&now);
strftime(yyyy, sizeof(yyyy), "%Y", mytime);
strftime(mm, sizeof(mm), "%m", mytime);
strftime(dd, sizeof(dd), "%d", mytime);
strftime(mname, sizeof(mname), "%B", mytime);
}
It crashes on localtime line:
Segmentation fault (core dumped)
Any ideas?
The sample code runs fine for me. Post your full code? Or cut down your example to minimal possible which still reproduces problem. And run gdb on your core 'gdb -c a.core a.out' and get a backtrace(bt).
One gotcha with localtime is the returned pointer is a pointer to a static global var and subsequent calls to localtime update the var. Tripped me up once long long ago.
struct tm *localtime(const time_t *time)
The return value is a pointer to a static broken-down time structure, which might be overwritten by subsequent calls to any of the date and time functions. (But no other library function overwrites the contents of this object.)
From:
http://www.chemie.fu-berlin.de/chemnet/use/info/libc/libc_17.html
On searching for core files:
See also core dumped - but core file is not in current directory?
Make sure system can write core file.
* for me on one sample ununtu system ulimit -c showed 0 *
ulimit -c unlimited
Check what pattern used and change the pattern to a simple one or different location.
cat /proc/sys/kernel/core_pattern
#sysctl -w kernel.core_pattern=core
Search some common locations and look in /var/log/messages:
ls /var/crash /var/cache/abrt /var/spool/abrt/ /tmp/*core*
tail /var/log/messages
On ubuntu examine the apport service config and init/rcfiles:
find /etc/ |grep appo
This may or may not be something close to your problem?
Still don't quite have enough info to be sure what you are doing.
I'd be thinking localtime is not the problem but somewhere in the printfs there are problems . . .
How are you compiling your project?
g++ or gcc?
Can you print a string?? (as opposed to string ptr)
What is a string in your context?
1 problem here:
fprintf(stdout,"# Single electron capture cross sections, %s state-selective\n",res);
If string is typedef a char[] then passing a pointer to it in func args would be better?
Compiling your sample making some assumptions and adding debug (-g3):
gcc -g3 stackoverflow_localtime_crash.c -o socrash
./socrash
# Single electron capture cross sections, RESSTRING state-selective
# Magic number=20032014, 20 March 2014,
# Single electron capture cross sections, RESSTRING state-selective
# ^0+ + -> ^-1+ + ^+
# Method=MCLZ
# et al. 2014, to be submitted
# ----------------------------------------------------------------------------
# Energy Cross sections (10^-16 cm^2)
# (eV/u) LABELSTRING �H���u�j
* lots more JUNK follows
res string itself cannot be passed in on stack and printed *
Segmentation fault (core dumped)
gdb -c core socrash
Core was generated by `./socrash'.
Program terminated with signal 11, Segmentation fault.
[New process 10298]
#0 0xb770e713 in strlen () from /lib/tls/i686/cmov/libc.so.6
(gdb) bt
#0 0xb770e713 in strlen () from /lib/tls/i686/cmov/libc.so.6
#1 0xb76da6d9 in vfprintf () from /lib/tls/i686/cmov/libc.so.6
#2 0xb76e0b9f in fprintf () from /lib/tls/i686/cmov/libc.so.6
#3 0x08048a42 in prtcsheader (cs=0xbf9e907c, labels=0xbf9e90bc, res=0xbf9e90a8 "RESSTRING") at stackoverflow_localtime_crash.c:66
#4 0x08048b36 in main (argc=Cannot access memory at address 0x0
) at stackoverflow_localtime_crash.c:80
(gdb) list
64 fprintf(stdout,"%-15s","# (eV/u)");
65 for(i=0;labels[i]!=NULL;i++)
66 fprintf(stdout,"\t%-14s",labels[i]);
67 fprintf(stdout,"\t%-14s","Total");
68
69 return 0;
(gdb)
* see line 66 there is also a problem *
might well be the way I have have declared string :-P
66 fprintf(stdout,"\t%-14s",labels[i]);
* If you can find a core file yourself then it would be a big help!!! *
If you can't find core then maybe you could use ltrace.
Run strace to get trace of all system calls a process does.
Run ltrace to get trace of all lib calls a process does.
Try:
strace ls
ltrace ls
On my crashing example:
ltrace ./socrash 1>stdout.log 2>socrash_ltrace.log
less socrash_ltrace.log

What does this mean in gdb?

Program received signal SIGSEGV, Segmentation fault.
0x08049795 in execute_jobs ()
Current language: auto; currently asm
(gdb) info symbol 0x08049795
execute_jobs + 22 in section .text
(gdb) ptype 0x08049795
type = int
How to get the line number at which the error occurred?
Your binary was not compiled with debugging information. Rebuild with at least -g (or -ggdb, or -ggdb -g3, see GCC manual.)
The exact lines from GDB output:
(gdb) info symbol 0x08049795 execute_jobs + 22 in section .text
means that instruction at address 0x08049795, which is 22 bytes from beginning of function execute_jobs, generated the segmentation fault.
(gdb) ptype 0x08049795 type = int
Here you are asking for type of an integer, and GDB happily replies. Do
(gdb) x/10i 0x08049795
or
(gdb) disassemble execute_jobs
to see actual instructions.
The gdb command "bt" will show you a back trace. Unless you've corrupted the stack this should show the sequence of function calls that lead to the segfault. To get more meaningful information make sure that you've compiled your program with debug information by including -g on the gcc/g++ command line.

Resources