Снять core dump linux

Использование дампов ядра для диагностики сбойных программ

Дампы ядра часто применяются для диагностики и поиска ошибок в Линуксовых и Юниксовых программах. Они помогут системному администратору выяснить, отчего рухнула та или иная программа, например, Lighttpd, Apache или PHP-CGI. Файл дампа ядра генерируется всякий раз, когда программа нештатно завершается из-за ошибки, нарушения политики безопасности операционной системы, попытки записывать данные вне отведенной ей области памяти и так далее. В этой статье рассказано, как подключить генерацию файлов дампов ядра и отслеживать с их помощью ошибки в программах.

Как подключить создание файлов дампа ядра

Как просмотреть текущие настройки файлов дампа ядра

Нулевой вывод команды означает, что файлы дампов не создаются.

Как изменить настройки

Как подключить генерацию файлов дампа ядра для рухнувших программ и ошибок сегментации

Найдите в /etc/profile строку

И измените ее, чтобы получилось:

Также следует внести изменения в файл /etc/sysctl.conf. В этот файл следует дописать три строки:

Не забудьте сохранить отредактированные файлы.

Что означают последние три записи?

    kernel.core_uses_pid = 1 ≈ добавляет к имени файла дампа номер PID процесса.

fs.suid_dumpable = 2 ≈ обеспечивает создание дампов ядра для программ с setuid битом.

kernel.core_pattern = /tmp/core-%e-%s-%u-%g-%p-%t ≈ Когда программа нештатно завершается, файл дампа появляется в директории /tmp. Благодаря параметру kernel.core_pattern, программа sysctl определяет конкретное имя файла дампа ядра. При помощи символа процента (%) могут быть заданы следующие значения:

  • %% ≈ одиночный символ %
  • %p ≈ PID дампируемого процесса
  • %u ≈ UID дампируемого процесса
  • %g ≈ GID дампируемого процесса
  • %s ≈ Номер сигнала, вызвавшего дампирование
  • %t ≈ время создания дампа (в секундах, с момента 0:00часов, 1 января 1970, то есть с условного момента создания ОС Юникс)
  • %h ≈ hostname (имя хоста), также как и ‘nodename’, возвращаемое командой uname(2)
  • %e ≈ имя исполняемого файла программы

Совершив все вышеописанные действия, запустите дампирование при помощи команды (Redhat и подобные дистрибутивы):

И запишите настройки в /etc/sysctl.conf при помощи следующей команды:

Как инициировать создание дампов ядра для конкретного демона

Например, для демона lighttped, в файл /etc/init.d/lighttped нужно добавить строку:

Сохраните файл. Затем перезапустите демон:

Правильный вывод последней команды:

Имейте в виду, что эта вышеприведенная строка является специфичной только для Redhat. Для всех остальных дистрибутивов конфигурацию прописывают строками:

Все, теперь можно отправлять дамп ядра разработчикам или распространителям программы.

Источник

Julia Evans

This week at work I spent all week trying to debug a segfault. I’d never done this before, and some of the basic things involved (get a core dump! find the line number that segfaulted!) took me a long time to figure out. So here’s a blog post explaining how to do those things!

At the end of this blog post, you should know how to go from “oh no my program is segfaulting and I have no idea what is happening” to “well I know what its stack / line number was when it segfaulted, at least!“.

what’s a segfault?

A “segmentation fault” is when your program tries to access memory that it’s not allowed to access, or tries to . This can be caused by:

  • trying to dereference a null pointer (you’re not allowed to access the memory address 0 )
  • trying to dereference some other pointer that isn’t in your memory
  • a C++ vtable pointer that got corrupted and is pointing to the wrong place, which causes the program to try to execute some memory that isn’t executable
  • some other things that I don’t understand, like I think misaligned memory accesses can also segfault

This “C++ vtable pointer” thing is what was happening to my segfaulting program. I might explain that in a future blog post because I didn’t know any C++ at the beginning of this week and this vtable lookup thing was a new way for a program to segfault that I didn’t know about.

Читайте также:  Mssoap soapclient windows 10

But! This blog post isn’t about C++ bugs. Let’s talk about the basics, like, how do we even get a core dump?

step 1: run valgrind

I found the easiest way to figure out why my program is segfaulting was to use valgrind: I ran

and this gave me a stack trace of what happened. Neat!

But I also wanted to do a more in-depth investigation and find out more than just what valgrind was telling me! So I wanted to get a core dump and explore it.

How to get a core dump

A core dump is a copy of your program’s memory, and it’s useful when you’re trying to debug what went wrong with your problematic program.

When your program segfaults, the Linux kernel will sometimes write a core dump to disk. When I originally tried to get a core dump, I was pretty frustrated for a long time because – Linux wasn’t writing a core dump!! Where was my core dump.

Here’s what I ended up doing:

  1. Run ulimit -c unlimited before starting my program
  2. Run sudo sysctl -w kernel.core_pattern=/tmp/core-%e.%p.%h.%t

ulimit: set the max size of a core dump

ulimit -c sets the maximum size of a core dump. It’s often set to 0, which means that the kernel won’t write core dumps at all. It’s in kilobytes. ulimits are per process – you can see a process’s limits by running cat /proc/PID/limit

For example these are the limits for a random Firefox process on my system:

The kernel uses the soft limit (in this case, “max core file size = 0”) when deciding how big of a core file to write. You can increase the soft limit up to the hard limit using the ulimit shell builtin ( ulimit -c unlimited !)

kernel.core_pattern: where core dumps are written

kernel.core_pattern is a kernel parameter or a “sysctl setting” that controls where the Linux kernel writes core dumps to disk.

Kernel parameters are a way to set global settings on your system. You can get a list of every kernel parameter by running sysctl -a , or use sysctl kernel.core_pattern to look at the kernel.core_pattern setting specifically.

So sysctl -w kernel.core_pattern=/tmp/core-%e.%p.%h.%t will write core dumps to /tmp/core-

If you want to know more about what these %e , %p parameters read, see man core.

It’s important to know that kernel.core_pattern is a global settings – it’s good to be a little careful about changing it because it’s possible that other systems depend on it being set a certain way.

kernel.core_pattern & Ubuntu

By default on Ubuntu systems, this is what kernel.core_pattern is set to

This caused me a lot of confusion (what is this apport thing and what is it doing with my core dumps??) so here’s what I learned about this:

  • Ubuntu uses a system called “apport” to report crashes in apt packages
  • Setting kernel.core_pattern=|/usr/share/apport/apport %p %s %c %d %P means that core dumps will be piped to apport
  • apport has logs in /var/log/apport.log
  • apport by default will ignore crashes from binaries that aren’t part of an Ubuntu packages

I ended up just overriding this Apport business and setting kernel.core_pattern to sysctl -w kernel.core_pattern=/tmp/core-%e.%p.%h.%t because I was on a dev machine, I didn’t care whether Apport was working on not, and I didn’t feel like trying to convince Apport to give me my core dumps.

So you have a core dump. Now what?

Okay, now we know about ulimits and kernel.core_pattern and you have actually have a core dump file on disk in /tmp . Amazing! Now what. We still don’t know why the program segfaulted!

The next step is to open the core file with gdb and get a backtrace.

Getting a backtrace from gdb

You can open a core file with gdb like this:

Next, we want to know what the stack was when the program crashed. Running bt at the gdb prompt will give you a backtrace. In my case gdb hadn’t loaded symbols for the binary, so it was just like . . Luckily, loading symbols fixed it.

Here’s how to load debugging symbols.

This loads symbols from the binary and from any shared libraries the binary uses. Once I did that, gdb gave me a beautiful stack trace with line numbers when I ran bt .

If you want this to work, the binary should be compiled with debugging symbols. Having line numbers in your stack traces is extremely helpful when trying to figure out why a program crashed 🙂

look at the stack for every thread

Here’s how to get the stack for every thread in gdb!

gdb + core dumps = amazing

If you have a core dump & debugging symbols and gdb, you are in an amazing situation!! You can go up and down the call stack, print out variables, and poke around in memory to see what happened. It’s the best.

Читайте также:  После включения ahci windows 10 не грузится

If you are still working on being a gdb wizard, you can also just print out the stack trace with bt and that’s okay 🙂

Another path to figuring out your segfault is to do one compile the program with AddressSanitizer (“ASAN”) ( $CC -fsanitize=address ) and run it. I’m not going to discuss that in this post because this is already pretty long and anyway in my case the segfault disappeared with ASAN turned on for some reason, possibly because the ASAN build used a different memory allocator (system malloc instead of tcmalloc).

I might write about ASAN more in the future if I ever get it to work 🙂

getting a stack trace from a core dump is pretty approachable!

This blog post sounds like a lot and I was pretty confused when I was doing it but really there aren’t all that many steps to getting a stack trace out of a segfaulting program:

if that doesn’t work, or if you want to have a core dump to investigate:

  1. make sure the binary is compiled with debugging symbols
  2. set ulimit and kernel.core_pattern correctly
  3. run the program
  4. open your core dump with gdb , load the symbols, and run bt
  5. try to figure out what happened!!

I was able using gdb to figure out that there was a C++ vtable entry that is pointing to some corrupt memory, which was somewhat helpful and helped me feel like I understood C++ a bit better. Maybe we’ll talk more about how to use gdb to figure things out another day!

You might also like the Recurse Center, my very favorite programming community (my posts about it)

Источник

Core dump

A core dump is a file containing a process’s address space (memory) when the process terminates unexpectedly. Core dumps may be produced on-demand (such as by a debugger), or automatically upon termination. Core dumps are triggered by the kernel in response to program crashes, and may be passed to a helper program (such as systemd-coredump) for further processing. A core dump is not typically used by an average user, but may be passed on to developers upon request where it can be invaluable as a post-mortem snapshot of the program’s state at the time of the crash, especially if the fault is hard to reliably reproduce.

Contents

Disabling automatic core dumps

Users may wish to disable automatic core dumps for a number of reasons:

  • Performance: generating core dumps for memory-heavy processes can waste system resources and delay the cleanup of memory.
  • Disk space: core dumps of memory-heavy processes may consume disk space equal to, if not greater, than the process’s memory footprint if not compressed.
  • Security: core dumps, although typically readable only by root, may contain sensitive data (such as passwords or cryptographic keys), which are written to disk following a crash.

Using sysctl

sysctl can be used to set the kernel.core_pattern to nothing to disable core dump handling. Create this file[1]:

To apply the setting immediately, use sysctl :

Using systemd

systemd’s default behavior is defined in /usr/lib/sysctl.d/50-coredump.conf , which sets kernel.core_pattern to call systemd-coredump . It generates core dumps for all processes in /var/lib/systemd/coredump . systemd-coredump behavior can be overridden by creating a configuration snippet in the /etc/systemd/coredump.conf.d/ directory with the following content[2][3]:

Then reload systemd’s configuration.

This method alone is usually sufficient to disable userspace core dumps, so long as no other programs enable automatic core dumps on the system, but the coredump is still generated in memory and systemd-coredump run.

Using PAM limits

The maximum core dump size for users logged in via PAM is enforced by limits.conf. Setting it to zero disables core dumps entirely. [4]

Using ulimit

Command-line shells such as bash or zsh provide a builtin ulimit command which can be used to report or set resource limits of the shell and the processes started by the shell. See bash(1) § SHELL BUILTIN COMMANDS or zshbuiltins(1) for details.

To disable core dumps in the current shell:

Making a core dump

To generate a core dump of an arbitrary process, first install the gdb package. Then find the PID of the running process, for example with pgrep:

Attach to the process:

Then at the (gdb) prompt:

Now you have a coredump file called core.2071 .

Where do they go?

The kernel.core_pattern sysctl decides where automatic core dumps go. By default, core dumps are sent to systemd-coredump which can be configured in /etc/systemd/coredump.conf . By default, all core dumps are stored in /var/lib/systemd/coredump (due to Storage=external ) and they are compressed with zstd (due to Compress=yes ). Additionally, various size limits for the storage can be configured.

Читайте также:  Docker build context windows

To retrieve a core dump from the journal, see coredumpctl(1) .

Examining a core dump

Use coredumpctl to find the corresponding dump:

You need to uniquely identify the relevant dump. This is possible by specifying a PID , name of the executable, path to the executable or a journalctl predicate (see coredumpctl(1) and journalctl(1) for details). To see details of the core dumps:

Pay attention to «Signal» row, that helps to identify crash cause. For deeper analysis you can examine the backtrace using gdb:

When gdb is started, use the bt command to print the backtrace:

See Debugging/Getting traces if debugging symbols are requested, but not found.

Источник

Отладка дампов Linux

Эта статья относится к: ✔️ пакету SDK для .NET Core 3.0 и более поздних версий

Сбор дампов в Linux

Два рекомендуемых способа сбора дампов в Linux:

  • Средство CLI dotnet-dump
  • Переменные среды для сборки дампов при аварийном завершении

Управляемые дампы с помощью dotnet-dump

Средство dotnet-dump просто в использовании и не зависит от каких-либо отладчиков машинного кода. dotnet-dump работает на различных платформах Linux (например, Alpine или ARM32/ARM64), где традиционные средства отладки могут быть недоступны. Однако dotnet-dump фиксирует только управляемое состояние, поэтому его нельзя использовать для отладки в машинном коде. Дампы, собранные dotnet-dump , анализируются в среде с той же ОС и архитектурой, в которой был создан дамп. Средство dotnet-gcdump можно использовать в качестве альтернативного варианта, которое фиксирует только сведения о куче GC, но создает дампы, которые можно проанализировать в Windows.

Дампы ядра с помощью createdump

Вместо dotnet-dump , создающего только управляемые дампы, createdump рекомендуется для создания основных дампов в Linux, содержащих как собственные, так и управляемые данные. Другие средства, такие как gdb или gcore, можно также использовать для создания основных дампов, однако они могут не учитывать состояние, необходимое для управляемой отладки, что приводит к неизвестному типу или именам функций во время анализа.

Средство createdump устанавливается вместе со средой выполнения .NET Core. Его можно найти рядом с libcoreclr.so (обычно в папке /usr/share/dotnet/shared/Microsoft.NETCore.App/[версия]). Средство использует идентификатор процесса для получения дампа в качестве основного аргумента, а также может принимать необязательные параметры, указывающие, какой тип дампа следует сохранять (по умолчанию используется малый дамп с кучей). Возможны следующие значения.

Исходный файл трассировки для преобразования. По умолчанию используется значение trace.nettrace.

Параметры

-f|—name

Файл, в который записывается дамп. Значение по умолчанию — «/tmp/coredump.%p», где % p — это идентификатор целевого процесса.

-n|—normal

-h|—withheap

Создание минидампа с кучей (по умолчанию).

-t|—triage

Создание минидампа для рассмотрения.

-u|—full

Создайте полного дампа ядра.

-d|—diag

Включение диагностических сообщений.

Для сбора дампов ядра требуется либо возможность SYS_PTRACE , либо createdump необходимо запустить с помощью sudo или su.

Анализ дампов в Linux

Как управляемые дампы, собранные с помощью dotnet-dump , так и дампы ядра, собранные с помощью createdump , можно проанализировать с помощью средства dotnet-dump , используя команду dotnet-dump analyze . dotnet dump требует, чтобы среда, в которой анализируется дамп, использовала ту же ОС и архитектуру, что и среда, в которой был записан дамп.

Кроме того, LLDB можно использовать для анализа основных дампов в Linux, что позволяет выполнять анализ как управляемых, так и собственных кадров. LLDB использует расширение SOS для отладки управляемого кода. Средство dotnet-sos CLI можно использовать для установки SOS, в котором содержится много полезных команд для отладки управляемого кода. Чтобы проанализировать дампы .NET Core, для LLDB и SOS требуются следующие двоичные файлы .NET Core из среды, в которой был создан дамп.

  1. libmscordaccore.so
  2. libcoreclr.so
  3. dotnet (узел, используемый для запуска приложения)

В большинстве случаев эти двоичные файлы можно скачать с помощью средства dotnet-symbol . Если необходимые двоичные файлы невозможно загрузить с помощью dotnet-symbol (например, если используется частная версия .NET Core, построенная на основе источника), может потребоваться скопировать перечисленные выше файлы из среды, в которой был создан дамп. Если файлы не расположены вместе с файлом дампа, можно использовать команду LLDB/SOS setclrpath

, чтобы задать путь, из которого они должны быть загружены, и setsymbolserver -directory

, чтобы задать путь для поиска файлов символов.

После того как необходимые файлы будут доступны, можно загрузить дамп в LLDB, указав узел dotnet в качестве исполняемого файла для отладки:

В приведенной выше командной строке — это путь к дампу для анализа, а — это собственная программа, запускающая приложение .NET Core. Обычно это двоичный файл dotnet , если приложение не является автономным. В этом случае это имя приложения без расширения DLL.

После запуска LLDB может потребоваться использовать команду setsymbolserver , чтобы указать правильное расположение символов ( setsymbolserver -ms , чтобы использовать сервер символов корпорации Майкрософт, или setsymbolserver -directory

для указания локального пути). Собственные символы можно загрузить, запустив loadsymbols . На этом этапе для анализа дампа можно использовать команды SOS.

Источник

Оцените статью