Привет отдыхающим. Хош не хош, а постом вас нужно порадовать и желательно интересным. Вот сейчас и порадую, самое время.

Сегодня будем дебажить и багфиксить. Узнаем что такое core файлы в Linux и как с ними взаимодействовать.

Иногда в Linux появляются какие-то странные файлы, с названием core.xxx, порой их бывает прям дохуя. Обычно их все сносят и не задумываются чо это за высер такой.

А этот высер можно либо отключить, либо залезть в него рукой и поковырять. На самом деле все эти «Корки», очень полезный материал для изучения и отладки падающих приложений.

Что такое «Корки»

Нет это не порода собаки. Всё просто, это файл, который содержит дамп памяти процесса в моменте, когда он уебался. То есть произошел segmentation fault.

Роман Шубин
Роман Шубин
CEO & CTO, Главред в «Цифровой улей»
Задать вопрос
Имея этот файл на руках, можно запатчить, забагфиксить либо понять откуда растут ноги у ошибки.

Как включить core файлы.

Хуй знает. Обычно это делается через файл /etc/sysctl.conf, добавляем:

kernel.core_pattern=core

Либо из консоли брякнуть:

sysctl -w kernel.core_pattern=core

В этом случае, если процесс/программа уебалась, то в папке с этим приложением появится файл core.xxx.

Важно! Выполняем:

ulimit -c

Если вернуло 0, то хуй те, а не «корка». Чтобы все сработало, выполняем команду:

ulimit -c unlimited

Так. У нас всё готово, по идее «корки» теперь будут создаваться. Если не создаются, то ты что-то сделал не так, либо в твоем дистрибутиве это делается иначе. Но я думаю это везде одинаково. Пробуй.

Пишем простой код на СИськах

#include <stdio.h>

int main() {
    int *ptr = NULL;
    *ptr = 10;
    return 0;
}

Компилируем:

gcc -g -o bashdays bashdays.c

Ключ -g включает отладочную информацию. Без этого ключа хуй мы чо отдебажим.

В коде выше, я пытаюсь присвоить значение 10 по адресу, на который указывает указатель ptr, но ptr не инициализирован и содержит значение NULL. В попытке разыменования указателя на NULL мы получим segmentation fault.

Сложно? Забей, нам важно понять как работать с «корками» и дебажить.

Так. Запускаем бинарник.

./bashdays

Хуяк и словили Segmentation fault (core dumped). Видишь в скобках core dumped? ВОТ ОНО! Рядом с бинарником появился файл core.1302. Полезли копаться в этом высере!

Запускаем отладчик:

gdb ./bashdays core.1302

Происходит магия. Чето там бежит и льется. Без паники! Смотрим несколько последних строчек:

Program terminated with signal SIGSEGV, Segmentation fault.
#0  0x0000563ebf37f13d in main () at coretest.c:5
5 *ptr = 10;

Тааак… и видим из-за чего была вызвана ошибка. Даже строчку показывает, которая справедлива для исходника, хотя мы смотрим бинарник.

Проверяем указатель ptr, вводим в отладчике:

(gdb) print ptr
$1 = (int *) 0x0

И видим что указатель ptr имеет значение NULL (0x0). Это и вызвало ошибку сегментации при попытке разыменования.

Теперь когда у нас есть эта инфа, мы знаем, что проблема заключается в попытке доступа к памяти по-нулевому указателю и можно это забагфиксить.

Самое простое решение, это добавить проверку и убедиться, что указатель ptr указывает на допустимую область памяти. Прежде чем разыменовывать его. Выделяем память для ptr с помощью функции malloc().

#include <stdio.h>
#include <stdlib.h>

int main() {
    int *ptr = malloc(sizeof(int)); // выделяем память для указателя
    if (ptr != NULL) { // если память выделена, присваиваем значение
        *ptr = 10;
        free(ptr); // освобождаем память
    } else {
        printf("Алярма! Память не выделяется\n");
    }
    return 0;
}

Вот и забагфиксили, компилируем, запускаем.

Ошибка сегментации исчезла. Улыбаемся и в очередной раз гордимся - какие же мы охуительные.

Но не достаточно! Чтобы прям вообще преисполниться, нужно запатчить бинарник через hex редактор.

Как это сделать, покажу совсем скоро, а то пост пиздец толстый получился.

У меня всё. Изучай.