00 Core dump nedir
Core dump, bir process çöktüğünde kernel tarafından oluşturulan process belleğinin anlık görüntüsüdür. Stack, heap, register durumu ve mapped dosyaları içerir. Çökme sonrası analiz (post-mortem debugging) için temel araçtır.
Çöküm sinyalleri
Core dump etkinleştirme
# Mevcut core dosya boyut limiti
ulimit -c
# 0 ← core dump devre dışı!
# Sınırsız core dump etkinleştir (session için)
ulimit -c unlimited
# Kalıcı ayar — /etc/security/limits.conf
echo "* soft core unlimited" >> /etc/security/limits.conf
echo "* hard core unlimited" >> /etc/security/limits.conf
# Core dosya adı ve konumu
cat /proc/sys/kernel/core_pattern
# core ← mevcut dizin
# /tmp/core.%e.%p.%t ← tam yol, program adı, PID, timestamp
# core_pattern format dizileri:
# %e = executable adı
# %p = PID
# %t = Unix timestamp
# %s = çöküm sinyali
# %u = UID
# %h = hostname
# systemd varsa coredump handler'a yönlendirir:
# |/usr/lib/systemd/systemd-coredump %P %u %g %s %t %c %h
Core dump içeriği
# ELF formatındaki core dosyasını incele
file core.1234
# core.1234: ELF 64-bit LSB core file, x86-64
# Program headers
readelf -l core.1234 | grep -E "LOAD|NOTE"
# NOTE segment'i — register, signal bilgisi
readelf -n core.1234 | head -30
01 systemd-coredump
systemd-coredump, core dump'ları otomatik olarak sıkıştırıp /var/lib/systemd/coredump/'a kaydeder. coredumpctl aracıyla listeler, inceler ve analiz araçlarına iletebilirsiniz.
systemd-coredump kurulumu
# Debian/Ubuntu
sudo apt install systemd-coredump
# core_pattern'i kontrol et — systemd pipe olmalı
cat /proc/sys/kernel/core_pattern
# |/usr/lib/systemd/systemd-coredump %P %u %g %s %t %c %h %e
# Konfigürasyon
cat /etc/systemd/coredump.conf
# [Coredump]
# Storage=external # /var/lib/systemd/coredump/'a kaydet
# Compress=yes # zstd ile sıkıştır
# ProcessSizeMax=2G # maksimum işlenecek boyut
# ExternalSizeMax=2G # harici dosya maksimumu
# JournalSizeMax=767M # journal'a yazılacak maksimum
coredumpctl komutları
# Tüm core dump'ları listele
coredumpctl list
# TIME PID UID GID SIG COREFILE EXE
# Sat 2026-01-15 14:23:11 UTC 1234 1000 1000 SIGSEGV present /usr/bin/myapp
# Belirli PID veya program için
coredumpctl list myapp
coredumpctl list 1234
# Detaylı bilgi (backtrace dahil)
coredumpctl info 1234
# PID: 1234 (myapp)
# Signal: 11 (SEGV)
# Timestamp: Sat 2026-01-15 14:23:11 UTC
# ...
# Stack trace of thread 1:
# #0 0x000055555555a123 crash_func (myapp.c:42)
# #1 0x000055555555b456 main (myapp.c:87)
# Core dosyasını dışarı aktar
coredumpctl dump 1234 -o /tmp/myapp.core
# GDB'yi doğrudan başlat
coredumpctl debug 1234
coredumpctl debug myapp # en son
Depolama yönetimi
# Kaydedilen core dump boyutları
ls -lh /var/lib/systemd/coredump/
# Eski dumpları temizle
journalctl --vacuum-size=500M # journal boyutunu sınırla
# coredumpctl ile sil
coredumpctl clean # eski ve artık yok olan binary'lerin dumpları
# Disk kullanımı
du -sh /var/lib/systemd/coredump/
02 Cross-architecture analiz
Embedded sistemlerden gelen ARM64 veya ARM32 core dump'larını, geliştirme makinesinde (x86-64) cross-GDB ve hedef sysroot kullanarak analiz etmek için adımlar.
Cross-GDB kurulumu
# ARM64 (aarch64) için cross-GDB
sudo apt install gdb-multiarch
# veya distro araç zincirine özgü:
sudo apt install gcc-aarch64-linux-gnu gdb-aarch64-linux-gnu
# Doğrulama
gdb-multiarch --version
aarch64-linux-gnu-gdb --version
# Kaynak koddan derle (son sürüm için):
# configure --target=aarch64-linux-gnu \
# --with-python \
# --enable-tui
Sysroot hazırlama
# Hedef cihazdan sysroot kopyala (rsync ile)
mkdir -p /opt/sysroot-aarch64
rsync -avz root@192.168.1.100:/{lib,usr/lib,usr/include} \
/opt/sysroot-aarch64/
# Buildroot sysroot (output/staging)
SYSROOT=/path/to/buildroot/output/staging
# Yocto SDK sysroot
source /opt/poky/4.0/environment-setup-cortexa72-poky-linux
echo $SDKTARGETSYSROOT
Cross-GDB ile core analizi
# ARM64 core dump'ı x86 host'ta analiz et
gdb-multiarch \
--ex "set sysroot /opt/sysroot-aarch64" \
--ex "set solib-search-path /opt/sysroot-aarch64/lib:/opt/sysroot-aarch64/usr/lib" \
--ex "set architecture aarch64" \
/opt/sysroot-aarch64/usr/bin/myapp \
/tmp/core.myapp.1234
# GDB içinde:
# (gdb) info sharedlibrary ← yüklenen kütüphaneler
# (gdb) bt ← backtrace
# (gdb) info registers ← register durumu
.gdbinit ile cross debug otomasyonu
# ~/.gdbinit veya proje dizininde .gdbinit
cat > .gdbinit <<'EOF'
set sysroot /opt/sysroot-aarch64
set solib-search-path /opt/sysroot-aarch64/lib
set solib-absolute-prefix /opt/sysroot-aarch64
set substitute-path /build/source /home/user/myproject/src
set architecture aarch64
set print pretty on
set print object on
EOF
# Çalıştır
gdb-multiarch ./myapp-aarch64 core.1234
03 GDB ile core analiz
GDB'nin core dump üzerindeki temel komutları: backtrace, frame navigasyonu, yerel değişkenler, register durumu ve bellek incelemesi.
Core yükleme ve backtrace
# Temel core analizi
gdb ./myapp core.1234
# GDB otomatik crash noktasını gösterir:
# Program terminated with signal SIGSEGV, Segmentation fault.
# #0 0x000055555555a123 in crash_func (ptr=0x0) at myapp.c:42
# 42 *ptr = 42; ← NULL deref!
# Tam backtrace
(gdb) bt
# #0 crash_func (ptr=0x0) at myapp.c:42
# #1 0x000055555555b456 in process_data (data=0x55555576a0a0) at myapp.c:75
# #2 0x000055555555c789 in main (argc=1, argv=0x7fffffffe068) at myapp.c:87
# Tüm thread'lerin backtrace
(gdb) thread apply all bt
Frame navigasyonu
# Belirli frame'e git
(gdb) frame 1
# #1 process_data (data=0x55555576a0a0) at myapp.c:75
# 75 crash_func(data->ptr);
# Frame bilgisi
(gdb) info frame
# Stack level 1, frame at 0x7fffffffdde0:
# rip = 0x55555555b456 in process_data (myapp.c:75)
# caller of frame at 0x7fffffffde00
# source language c.
# Yerel değişkenler
(gdb) info locals
# data = 0x55555576a0a0
# result = 0
# Fonksiyon argümanları
(gdb) info args
# data = 0x55555576a0a0
Register ve bellek inceleme
# Tüm register'lar
(gdb) info registers
# rax 0x0 0
# rbx 0x55555576a0a0 93824994713760
# rsp 0x7fffffffddc0 0x7fffffffddc0
# rip 0x55555555a123 0x55555555a123 <crash_func+35>
# Belirli register
(gdb) p/x $rip
(gdb) p/x $rsp
# Bellek inceleme (examine)
# x/[N][fmt][unit] addr
# fmt: x=hex, d=dec, s=string, i=instr, b=byte
(gdb) x/10xw 0x55555576a0a0 # 10 word, hex
(gdb) x/s 0x55555576a0b0 # string
(gdb) x/5i $rip # 5 assembly instruction
(gdb) x/32xb $rsp # stack'in 32 byte'ı
Değişken ve ifade değerlendirme
# Değişken değerini göster
(gdb) p data
# $1 = (struct mydata *) 0x55555576a0a0
# Struct üyelerini göster
(gdb) p *data
# $2 = {ptr = 0x0, len = 42, name = 0x55555555d123 "test"}
(gdb) p data->len
# $3 = 42
# Bellek adresindeki struct'ı cast et
(gdb) p *(struct mydata*)0x55555576a0a0
# Python ile GDB scripting
(gdb) python print([gdb.parse_and_eval(f"$r{i}") for i in range(13)])
04 addr2line ve nm
addr2line bir adres veya offset'i kaynak dosya + satır numarasına çevirir. nm binary'deki sembolleri listeler. Her ikisi de GDB olmadan hızlı crash tespiti sağlar.
addr2line kullanımı
# Crash adresini kaynak satıra çevir
addr2line -e myapp -a 0x55555555a123 -f -p -i
# 0x55555555a123: crash_func at /home/user/myapp.c:42
# (inlined by) process_data at /home/user/myapp.c:75
# Parametreler:
# -e binary : ELF dosyası
# -a addr : adres
# -f : fonksiyon adını göster
# -p : güzel çıktı (pretty-print)
# -i : inline fonksiyonları göster
# -C : C++ mangled isimlerini demangling
# Birden fazla adres
addr2line -e myapp -f \
0x55555555a123 \
0x55555555b456 \
0x55555555c789
# ARM64 binary (cross-toolchain)
aarch64-linux-gnu-addr2line -e myapp-arm64 -f -p \
0x000000000001a123
nm ile sembol arama
# Tüm sembolleri listele
nm myapp | head -20
# 0000000000001234 T crash_func ← Text (kod)
# 0000000000002000 D global_data ← Data (init)
# 0000000000003000 B global_bss ← BSS (uninit)
# 0000000000004000 R const_string ← Read-only
# Sembol türleri:
# T/t: kod (Text) D/d: init data B/b: BSS
# U: undefined W: weak I: indirect
# Belirli sembol ara
nm myapp | grep crash_func
nm myapp | grep -i "malloc\|free"
# Offset'e göre yakın sembolü bul
nm --numeric-sort myapp | awk -v addr=0x55555555a100 '
BEGIN { target=strtonum(addr) }
{ cur=strtonum("0x"$1); if(cur<=target) { prev=$0; prevaddr=cur } else { print prev; exit } }
'
Mapfile analizi
# Linker map dosyası (derleme sırasında oluştur)
gcc -Wl,-Map,myapp.map -o myapp myapp.c
# Map'ten crash adresinin lokasyonu
grep -A2 "0x55555555a" myapp.map
# Objdump ile disassemble + kaynak
objdump -d -S --source myapp | grep -A 20 "<crash_func>"
05 ASAN core dump
AddressSanitizer (ASAN), stack/heap taşmaları ve use-after-free hatalarını derleme zamanı enstrümantasyonu ile tespit eder. Core dump ile kombine edildiğinde tam hata analizi sağlar.
ASAN ile derleme
# ASAN etkinleştirme
gcc -fsanitize=address \
-fsanitize=undefined \
-fno-omit-frame-pointer \
-g \
-O1 \
-o myapp myapp.c
# CMake ile
cmake -DCMAKE_C_FLAGS="-fsanitize=address -fno-omit-frame-pointer" \
-DCMAKE_EXE_LINKER_FLAGS="-fsanitize=address" ..
# Clang ile daha iyi raporlar
clang -fsanitize=address,undefined \
-fsanitize-recover=all \
-fno-omit-frame-pointer -g -O1 \
-o myapp myapp.c
ASAN runtime ortam değişkenleri
# ASAN core dump oluştur
ASAN_OPTIONS="abort_on_error=1:disable_coredump=0:unmap_shadow_on_exit=1" \
ulimit -c unlimited && ./myapp
# Tüm ASAN seçenekleri
ASAN_OPTIONS=help=1 ./myapp 2>&1 | head -30
# Önemli seçenekler:
# abort_on_error=1 → hata = SIGABRT → core dump
# disable_coredump=0 → core dump'u engelleme
# symbolize=1 → anlık sembol çözümü
# halt_on_error=1 → ilk hatada dur
# detect_leaks=1 → leak tespiti (LSan)
# log_path=/tmp/asan.log → log dosyası
ASAN çıktısı örneği ve analiz
# Heap buffer overflow:
ASAN_OPTIONS="abort_on_error=1" ./myapp
# =================================================================
# ==1234==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x602000000028
# READ of size 4 at 0x602000000028 thread T0
# #0 0x55a123456789 in read_data myapp.c:55
# #1 0x55a123456abc in main myapp.c:88
#
# 0x602000000028 is located 8 bytes to the right of 32-byte region
# [0x602000000000,0x602000000020)
# allocated by thread T0 here:
# #0 0x7f... in __interceptor_malloc
# #1 0x55a123456def in alloc_buffer myapp.c:40
# Use-after-free:
# ==1234==ERROR: AddressSanitizer: heap-use-after-free on address 0x603000000030
# WRITE of size 8 at 0x603000000030 thread T0
# #0 0x55a... in bad_write myapp.c:67
# core dump'ı gdb ile analiz et:
ASAN_SYMBOLIZER_PATH=$(which llvm-symbolizer) \
gdb ./myapp core.1234
Cross-compiled ASAN (ARM64)
# Yocto'da ASAN etkinleştirme (local.conf)
# EXTRA_OEMAKE:append = " CFLAGS='-fsanitize=address -g'"
# libasan paylaşımlı kütüphanesini hedefe kopyala
scp /usr/aarch64-linux-gnu/lib/libasan.so.* root@device:/usr/lib/
# Cihazda çalıştır
ssh root@device "ASAN_OPTIONS='abort_on_error=1' ulimit -c unlimited; ./myapp"
# Core'u host'a çek ve analiz et
scp root@device:/tmp/core.myapp.* ./
aarch64-linux-gnu-gdb ./myapp-arm64 core.myapp.1234
06 Kernel oops/panic analiz
Kernel oops, kernel içindeki hata durumunu (NULL deref, use-after-free, stack overflow) raporlar. Panic, kurtarılamaz bir hatadır. Her ikisi de dmesg/serial console üzerinden analiz edilir.
Kernel oops formatı
# Tipik kernel oops — dmesg çıktısı:
dmesg | grep -A 30 "BUG\|Oops\|general protection"
# Örnek oops:
# BUG: kernel NULL pointer dereference, address: 0000000000000010
# #PF: supervisor read access in kernel mode
# #PF: error_code(0x0000) - not-present page
# PGD 0 P4D 0
# Oops: 0000 [#1] SMP PTI
# CPU: 2 PID: 1234 Comm: mymodule Tainted: G OE 5.15.0
# Hardware name: ...
# RIP: 0010:bad_kernel_func+0x35/0x80 [mymodule]
# RSP: 0018:ffffb12345678d48 EFLAGS: 00010286
# Call Trace:
# <TASK>
# another_func+0x12/0x40 [mymodule]
# module_entry+0x45/0xa0 [mymodule]
# do_one_initcall+0x46/0x200
%pS — sembol çözme
# Kernel oops'taki adres sembolünü çöz
# RIP: 0010:bad_kernel_func+0x35/0x80
# addr2line ile kernel modül sembol çözme:
addr2line -e /lib/modules/$(uname -r)/extra/mymodule.ko \
-f -p 0x35
# kallsyms ile sembol ara
grep bad_kernel_func /proc/kallsyms
# ffffffffc0a12300 t bad_kernel_func [mymodule]
# scripts/decode_stacktrace.sh (kernel kaynak)
dmesg | scripts/decode_stacktrace.sh vmlinux . modules/
kdump / crash — kernel crash analizi
# kdump kurulumu (Debian/Ubuntu)
sudo apt install kdump-tools crash linux-image-$(uname -r)-dbg
# /etc/default/kdump-tools
# USE_KDUMP=1
# KDUMP_KERNEL=/boot/vmlinuz-$(uname -r)
# Crash tool ile vmcore analizi
crash /usr/lib/debug/boot/vmlinux-5.15.0 /var/crash/vmcore
# crash komutları:
# bt ← backtrace (çöken process)
# bt -a ← tüm process'ler
# ps ← process listesi
# log ← dmesg ring buffer
# files PID ← açık dosyalar
# vm ← virtual memory
# dev ← cihaz bilgisi
Kernel taint flags
cat /proc/sys/kernel/tainted
# Değer bit maskeleri:
# 0 = temiz
# 1 = proprietary module yüklü
# 2 = out-of-tree module
# 4 = SMP sorunu
# 64 = machine check exception
# dmesg'de Tainted: anlamı
# Tainted: G = proprietary driver
# Tainted: O = out-of-tree module
# Tainted: E = unsigned module (Secure Boot)
07 Automated crash reporting
Üretim ortamındaki embedded cihazlarda manuel analiz mümkün değildir. Google Breakpad/Crashpad, minidump formatı ve remote symbol server ile otomatik crash raporlama kurulumu.
Google Breakpad entegrasyonu
# Breakpad klonla ve derle
git clone https://chromium.googlesource.com/breakpad/breakpad
cd breakpad
./configure && make
# ARM64 için cross-compile
./configure --host=aarch64-linux-gnu \
CC=aarch64-linux-gnu-gcc \
CXX=aarch64-linux-gnu-g++
make
Breakpad C++ entegrasyon kodu
#include "client/linux/handler/exception_handler.h"
#include <string>
static bool MinidumpCallback(const google_breakpad::MinidumpDescriptor &descriptor,
void *context, bool succeeded) {
fprintf(stderr, "Minidump: %s\n", descriptor.path());
// Burada minidump'ı uzak sunucuya yükle
return succeeded;
}
int main(int argc, char *argv[]) {
google_breakpad::MinidumpDescriptor descriptor("/tmp/minidumps");
google_breakpad::ExceptionHandler eh(
descriptor,
nullptr, // filter callback
MinidumpCallback,
nullptr, // context
true, // install handler
-1 // server fd
);
/* Normal uygulama kodu */
return 0;
}
Symbol server ve minidump analizi
# Binary'den symbol dosyası oluştur
dump_syms ./myapp > /symbols/myapp/BUILD_ID/myapp.sym
# Symbol server dizin yapısı:
# symbols/
# myapp/
# A3B4C5D6E7F8.../ ← Build ID
# myapp.sym
# Minidump'ı analiz et
minidump_stackwalk /tmp/minidumps/crash.dmp /symbols/
# Otomatik upload scripti
cat > /usr/local/bin/upload_crash.sh <<'EOF'
#!/bin/bash
DUMP_FILE=$1
DEVICE_ID=$(cat /etc/machine-id)
curl -F "dump=@$DUMP_FILE" \
-F "device=$DEVICE_ID" \
-F "version=$(cat /etc/app-version)" \
https://crash.example.com/upload
EOF
Crashpad (Breakpad halefi)
# Crashpad — Chrome/Electron kullanıyor
git clone https://chromium.googlesource.com/crashpad/crashpad
# Crashpad handler başlatma (C++)
# #include "client/crashpad_client.h"
# CrashpadClient client;
# client.StartHandler(
# base::FilePath("/usr/lib/crashpad_handler"),
# base::FilePath("/tmp/crashes"),
# base::FilePath("/tmp/crashes"),
# "https://crash.example.com/api",
# {}, // annotations
# {"--no-rate-limit"}, // arguments
# false // restartable
# );
08 Pratik: NULL deref + stack overflow → tam backtrace pipeline
Kasıtlı NULL deref ve stack overflow hataları oluşturarak, core dump alıp tam backtrace analizini gerçekleştiren adım adım pipeline.
Adım 1: Test programı — kasıtlı hatalar
/* crash_test.c — eğitim amaçlı kasıtlı crash'ler */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
/* NULL pointer dereference */
void null_deref_crash(void) {
int *ptr = NULL;
printf("About to crash: NULL deref\n");
*ptr = 42; /* SIGSEGV */
}
/* Stack overflow — sonsuz özyineleme */
void stack_overflow(int depth) {
char local_buf[4096]; /* her frame 4KB stack tüketir */
memset(local_buf, depth & 0xFF, sizeof(local_buf));
printf("depth=%d sp=%p\n", depth, local_buf);
stack_overflow(depth + 1); /* SIGSEGV — stack exhausted */
}
/* Heap buffer overflow */
void heap_overflow(void) {
char *buf = malloc(16);
memset(buf, 'A', 64); /* 48 byte taşma */
free(buf); /* SIGABRT — heap corruption */
}
int main(int argc, char *argv[]) {
if (argc < 2) {
fprintf(stderr, "Usage: %s [null|stack|heap]\n", argv[0]);
return 1;
}
if (strcmp(argv[1], "null") == 0) null_deref_crash();
if (strcmp(argv[1], "stack") == 0) stack_overflow(0);
if (strcmp(argv[1], "heap") == 0) heap_overflow();
return 0;
}
Adım 2: Debug sembollerle derleme
# Debug sembollerle derle
gcc -g -O0 -fno-omit-frame-pointer \
-o crash_test crash_test.c
# ARM64 cross-compile
aarch64-linux-gnu-gcc -g -O0 -fno-omit-frame-pointer \
-o crash_test_arm64 crash_test.c
Adım 3: Core dump oluşturma
# Core dump etkinleştir ve programı çalıştır
ulimit -c unlimited
export CORE_DIR=/tmp/cores
mkdir -p $CORE_DIR
# core_pattern'i ayarla
sudo bash -c "echo '$CORE_DIR/core.%e.%p.%s.%t' > /proc/sys/kernel/core_pattern"
# NULL deref testi
./crash_test null
ls -la $CORE_DIR/
# -rw------- 1 user user 278528 Jan 15 14:23 core.crash_test.1234.11.1705330987
# Stack overflow testi
./crash_test stack
# (birkaç saniye çalışır, sonra SIGSEGV)
Adım 4: GDB ile analiz
# NULL deref core analizi
gdb -q ./crash_test $CORE_DIR/core.crash_test.1234.11.*
# GDB çıktısı:
# Reading symbols from ./crash_test...
# [New LWP 1234]
# Core was generated by `./crash_test null'.
# Program terminated with signal SIGSEGV, Segmentation fault.
# #0 0x000055555555527a in null_deref_crash () at crash_test.c:11
# 11 *ptr = 42;
(gdb) bt
# #0 null_deref_crash () at crash_test.c:11
# #1 0x00005555555552f8 in main (argc=2, argv=0x7fffffffe068) at crash_test.c:29
(gdb) info locals
# ptr = 0x0 ← NULL pointer!
(gdb) p ptr
# $1 = (int *) 0x0
(gdb) x/3i $rip-5
# 0x555555555275 <null_deref_crash+15>: mov DWORD PTR [rax],0x2a
# ← 0x2a = 42 decimal, rax=0x0 → NULL write
Adım 5: addr2line ile doğrulama
# GDB backtrace adreslerini kaynak satırlarına çevir
addr2line -e ./crash_test -f -p -i \
0x000055555555527a \
0x00005555555552f8
# Çıktı:
# 0x000055555555527a: null_deref_crash at crash_test.c:11
# 0x00005555555552f8: main at crash_test.c:29
Adım 6: Stack overflow analizi
gdb -q ./crash_test $CORE_DIR/core.crash_test.*.11.*
# (gdb) bt
# Stack overflow sonsuz backtrace gösterir, sonunda kesilir:
# #0 stack_overflow (depth=2847) at crash_test.c:18
# #1 0x00005555555551f8 in stack_overflow (depth=2846) at crash_test.c:20
# #2 0x00005555555551f8 in stack_overflow (depth=2845) at crash_test.c:20
# ... (2847 frame tekrar)
# Stack pointer → stack limitine ulaşmış
(gdb) p $rsp
(gdb) info proc mappings
# [stack] 0x7fff0000000 - 0x800000000 (8 MB)
# rsp'nin bu aralık dışına çıktığını gösterir
Core dump analiz pipeline şu adımlardan oluşur: (1) ulimit -c unlimited + core_pattern ayarı, (2) debug sembollü derleme, (3) çöküşü tetikle + core kaydet, (4) GDB ile bt/frame/info locals, (5) addr2line ile satır doğrulama. Cross-architecture için gdb-multiarch + hedef sysroot zorunludur. Production sistemlerde Breakpad/Crashpad ile minidump otomatik toplanabilir.