Category Archives: C

Core dump is not generated on Ubuntu in some cases

Core dump is not generated on Ubuntu(14.04 LTS) in some cases.
Sometimes it can be generated. It seems to depend on the program.

Like below ulimit is OK.

$ ulimit -c unlimited
$ ulimit -a
core file size          (blocks, -c) unlimited
data seg size           (kbytes, -d) unlimited
scheduling priority             (-e) 0
file size               (blocks, -f) unlimited
pending signals                 (-i) 15739
max locked memory       (kbytes, -l) 64
max memory size         (kbytes, -m) unlimited
open files                      (-n) 1024
pipe size            (512 bytes, -p) 8
POSIX message queues     (bytes, -q) 819200
real-time priority              (-r) 0
stack size              (kbytes, -s) 8192
cpu time               (seconds, -t) unlimited
max user processes              (-u) 15739
virtual memory          (kbytes, -v) unlimited
file locks                      (-x) unlimited

I examined where the core dump is generated.

$ sudo sysctl -a | grep core_pattern
kernel.core_pattern = |/usr/share/apport/apport %p %s %c %P

On Ubuntu(14.04 LTS) core_pattern uses apport by default.

In case core dump was successfully generated, core dump was generated in current directory.
In case core dump was not generated, an error occurred on apport.

/var/log/apport.log

ERROR: apport (pid 3480) Tue May 12 18:48:31 2015: called for pid 3479, signal 6, core limit 18446744073709551615
ERROR: apport (pid 3480) Tue May 12 18:48:31 2015: ignoring implausibly big core limit, treating as unlimited
ERROR: ERROR: apport (pid 3480) Tue May 12 18:48:31 2015: Unhandled exception:
Traceback (most recent call last):
  File "/usr/share/apport/apport", line 357, in <module>
    (info['ExecutablePath'], info['ProcCmdline']))
  File "/usr/share/apport/apport", line 99, in error_log
    apport.error('apport (pid %s) %s: %s', os.getpid(), time.asctime(), msg)
  File "/usr/lib/python3/dist-packages/apport/__init__.py", line 44, in error
    sys.stderr.write(msg % args)
UnicodeEncodeError: 'ascii' codec can't encode character '\ufffd' in position 143: ordinal not in range(128)
ERROR: apport (pid 3480) Tue May 12 18:48:31 2015: pid: 3480, uid: 0, gid: 0, euid: 0, egid: 0
ERROR: apport (pid 3480) Tue May 12 18:48:31 2015: environment: environ({})

Because an error occurred on apport, core dump was not generated.
This error seems to be Python's error but I'm not sure, so I decided not to use apport in core_pattern.

# echo 'core.%e.%p' > /proc/sys/kernel/core_pattern
$ ulimit -c unlimited
$ cat segfault.c
#include <stdio.h>

int main(void)
{
  char *s = "hello, world!";
  *s = 'H';

  return 0;
}
$ gcc -Wall -g -o segfault segfault.c
$ ./segfault 
Segmentation fault (core dumped)
$ ls
core.segfault.3423  segfault  segfault.c

Any configuration changes made using the echo command disappear when the system is restarted.
To make configuration changes take effect after the system is rebooted, edit /etc/sysctl.conf.

Source: E.4. Using the sysctl Command

/etc/sysctl.conf

kernel.core_pattern = core.%e.%p

But when the system is restarted, changes disappear and core_pattern uses apport.
When the system is restarted and apport starts, apport seems to overwrite configuration.

Source: 12.04 - How to permanently edit the core_pattern file? - Ask Ubuntu

To stop this behavior, disable apport and restart the system.

/etc/default/apport

# set this to 0 to disable apport, or to 1 to enable it
# you can temporarily override this with
# sudo service apport start force_start=1
#enabled=1
enabled=0

If the return value of a command is greater than 128, it means that the command is terminated by signal

If the return value of a command is greater than 128, it means that the command is terminated by signal.

$ man bash
The return value of a simple command is its exit status, or 128+n if the command is terminated by signal n.

Example:

$ some_command
$ echo $?
139

In the above example, the return value is 139. Because 139=128+11 it means that the command was terminated by signal 11.
See `man signal` and you will find that signal 11 is SIGSEGV and it means segmentation violation.

Print a pointer as an array using GDB

You can print an array using `print` command (p) with GDB, but it is useful to print a pointer such as function parameter as an array using operator @.
Operator @ regards the left operand of @ as the address and prints the data of the left operand as an array for the number equivalent to the right operand.

(gdb) list
34
35	void func(int v[], int len)
36	{
(gdb) p v[0] @ len
$1 = {4470, 5197, 2482, 1016, 4154, 9986, 8313, 6873, 8517, 5857, 9019, 8002, 349, 9817, 365, 1018, 2269, 9759, 7092, 8674, 4902, 3890, 9746, 7668, 792, 3842, 4053, 6422, 630, 4880, 9996, 7164, 8392, 8469, 2959, 8380, 6533, 1795, 4296, 9964, 8259, 7474, 72, 2948, 3681, 501, 3994, 508, 9544, 941, 8054, 2186, 7418, 8684, 3224, 7322, 3822, 5022, 3085, 8341, 2296, 4073, 1034, 9839, 7067, 1197, 739, 7028, 2809, 6610, 8633, 483, 3017, 9634, 4758, 8101, 7604, 4018, 2174, 5014, 6600, 3754, 2854, 4798, 3921, 2124, 9889, 1147, 2409, 6105, 224, 6973, 5937, 2953, 8614, 9101, 3399, 8431, 2226, 3548}

Source: Arrays - Debugging with GDB

Find real type of typedef such as system data types

The easiest way is to use ptype with gdb.

Example:

foo.c

#include <sys/types.h>
struct st { int i; char c; };
typedef int Array[10];
typedef struct st St;
int main(void)
{ 
  size_t s1;
  ssize_t s2;
  pid_t pid;
  Array arr;
  St st1;
  return 0;
}
$ gcc -Wall -g -o foo foo.c
$ gdb foo
(gdb) b main
(gdb) run
(gdb) ptype s1
type = long unsigned int
(gdb) ptype size_t
type = long unsigned int
(gdb) ptype s2
type = long int
(gdb) ptype ssize_t 
type = long int
(gdb) ptype pid
type = int
(gdb) ptype pid_t
type = int
(gdb) ptype arr
type = int [10]
(gdb) ptype Array 
type = int [10]
(gdb) ptype st1
type = struct st {
    int i;
    char c;
}
(gdb) ptype St
type = struct st {
    int i;
    char c;
}

Like the above example,

ptype <expression or type name>

shows real type.

If the type is an array, it also shows its size. If the type is a struct, it also shows the type of the members of the struct. It's convenient.

You can probably find the real type using gcc -E option and looking into preprecessor's output like below, but it's bothersome and possibly needs hard work.

$ gcc -E foo.c | grep ssize_t
typedef long int __ssize_t;
typedef __ssize_t ssize_t;
(ommitted below)

In the above example (x86_64 GNU/Linux), you can find that ssize_t is
__ssize_t => long int

$ gcc -E foo.c | grep ssize_t
typedef long __darwin_ssize_t;
(ommitted)
typedef __darwin_ssize_t ssize_t;
(ommitted)

In the above example (Mac OS X), you can find that ssize_t is
ssize_t => __darwin_ssize_t => long