π 2016-Aug-13 ⬩ βοΈ Ashwin Nanjappa ⬩ π·οΈ apport, core dump ⬩ π Archive
When your program tries to do anything nasty, like access memory it is not supposed to, you end up seeing a core dump.
If you ran the program under the Bash shell, you might see this error:
$ ./my_program
Segmentation fault (core dumped)
Under the Fish shell, I see this error:
$ ./my_program
fish: β./my_programβ terminated by signal SIGSEGV (Address boundary error)
If I check the directory I ran the program from, I see that there is a core
file that has the entire dump of the process memory from when the program did its nasty act.
How did a SIGSEGV
end up as a core dump file? This is what I found in Ubuntu:
/var/log/syslog
with some information about what happened. Here is the line on my computer:Aug 13 17:56:09 my_machine kernel: [442853.259571] my_program[18432]: segfault at 4700000046 ip 00007f7688f6980d sp 00007ffd46b5e3e0 error 4 in libc-2.23.so[7f7688f30000+1c0000]
The Linux kernel checks what settings are present for writing a core dump. There are 3 settings, which are in the files core_pattern
, core_pipe_limit
and core_uses_pid
in /proc/sys/kernel
directory. The documentation of these settings can be found described in kernel.txt.
core_pattern
says what the filename of the core dump file should be. On my Ubuntu, this setting had this value:
$ cat /proc/sys/kernel/core_pattern
|/usr/share/apport/apport %p %s %c %P
From the kernel.txt documentation, we can see that this means that the kernel has to call the /usr/share/apport/apport
executable with four input arguments. The first, second and fourth arguments are documented as PID of offending process, signal number and global PID. We do not know what the %c
does, but we will find out soon below. The kernel will pipe the process memory to the standard input of this apport program.
$ file /usr/share/apport/apport
/usr/share/apport/apport: Python script, ASCII text executable
That is great, because we can open it and read its code to see what it does!
%c
input argument is the ulimit
value set in our shell:Line 393: (pid, signum, core_ulimit) = sys.argv[1:4]
We can also see what exactly it does to write the core dump in its function write_user_coredump
. In short, this function checks the ulimit
value of the shell and then decides how many bytes to write to the core file and writes it to the same directory as the program.
We also see that it called error_log
to write some log messages. These can be found listed in the /var/log/apport.log
file:
ERROR: apport (pid 18475) Sat Aug 13 17:56:18 2016: called for pid 18474, signal 11, core limit 102400000
ERROR: apport (pid 18475) Sat Aug 13 17:56:18 2016: executable: /home/joe/my_program (command line "./my_program")
ERROR: apport (pid 18475) Sat Aug 13 17:56:18 2016: executable does not belong to a package, ignoring
ERROR: apport (pid 18475) Sat Aug 13 17:56:18 2016: writing core dump to /home/joe/core (limit: 102400000)
This is how Ubuntu writes the core dump file. You can now open this up in GDB for debugging! π
Tried with: Ubuntu 16.04