00 Debugging araçları taksonomisi
Her debugging problemi üç kategoriden birine girer: davranış hatası, performans sorunu veya memory bozulması — doğru aracı seçmek sorunun yarısını çözer.
Üç problem kategorisi
Bir Linux uygulamasında bir şeyler yanlış gittiğinde sorunun kaynağı genellikle şu üç kategoriden birinde yatar: programın syscall seviyesinde yanlış davranması (dosya açamıyor, bağlanamıyor, izin hatası), performans sorunu (CPU, bellek veya I/O darboğazı), ya da memory management hatası (leak, corruption, double free). Her kategori için farklı bir araç takımı kullanılır.
| Araç | Kategori | Ne Gösterir | Overhead |
|---|---|---|---|
| strace | Davranış | Syscall'lar: argüman, dönüş değeri, hata kodu | Yüksek (~10x) |
| ltrace | Davranış | Dinamik kütüphane çağrıları (libc, libssl vb.) | Yüksek |
| perf | Performans | CPU cycle, cache miss, branch mispredict, flamegraph | Çok düşük (<1%) |
| valgrind | Memory | Leak, invalid read/write, double free, use-after-free | Çok yüksek (2–10x) |
| ASan | Memory | Buffer overflow, use-after-free, stack corruption | Orta (~2x) |
| TSan | Memory / Concurrency | Race condition, lock-order violation | Yüksek (5–15x) |
Karar rehberi: hangi araç ne zaman?
Problem nedir?
│
├─ "Dosya açılmıyor / bağlanamıyor / izin hatası"
│ └──→ strace -e trace=file,network
│
├─ "Uygulama çok yavaş, CPU çok yüksek"
│ └──→ perf top → perf record -g → flamegraph
│
├─ "Bellek sürekli artıyor"
│ └──→ valgrind --leak-check=full
│ ya da /proc/PID/smaps + heaptrack
│
├─ "Segfault / crash"
│ └──→ core dump + gdb → ASan → valgrind
│
└─ "Race condition / deadlock"
└──→ ThreadSanitizer (-fsanitize=thread)
Kurulum
# Debian / Ubuntu
sudo apt install strace ltrace linux-perf valgrind
# RHEL / CentOS / Fedora
sudo yum install strace ltrace perf valgrind
# perf kernel sürümü doğrula
perf --version
uname -r
# perf paranoia seviyesini düşür (root olmadan kullanmak için)
sudo sysctl kernel.perf_event_paranoid=1
Bu bölümde öğrendikleriniz
- Debugging problemleri davranış, performans ve memory olmak üzere üç kategoriye ayrılır
- strace/ltrace syscall ve library çağrılarını; perf CPU metriklerini; valgrind/ASan memory hatalarını yakalar
- Doğru araç seçimi debug süresini ciddi ölçüde kısaltır
01 strace temelleri
strace, ptrace() syscall'ını kullanarak hedef process'in her kernel çağrısını yakalar ve terminale basar — program ile kernel arasında bir cam duvar gibi davranır.
strace nasıl çalışır?
strace, Linux kernel'in ptrace() mekanizmasını kullanır. PTRACE_SYSCALL isteğiyle hedef process her syscall'a girerken ve çıkarken durdurulur; argümanlar ve dönüş değeri okunarak terminale yazdırılır. Bu nedenle overhead yüksektir — production'da dikkatli kullanılmalıdır.
user space kernel space
│ │
myapp ──── syscall ───────→│
│ (giriş) │← strace buraya hook eder
│ │ argümanları okur
│ kernel işler
│ │← strace çıkışa hook eder
myapp ←── dönüş ───────────│ dönüş değerini okur
│ │
İlk çalıştırma: strace ls
strace ls /tmp 2>&1 | head -20
Tipik çıktı (kısaltılmış):
execve("/usr/bin/ls", ["ls", "/tmp"], 0x... /* env vars */) = 0
brk(NULL) = 0x55f8c2a01000
openat(AT_FDCWD, "/etc/ld.so.cache", O_RDONLY|O_CLOEXEC) = 3
fstat(3, {st_mode=S_IFREG|0644, st_size=89432, ...}) = 0
mmap(NULL, 89432, PROT_READ, MAP_PRIVATE, 3, 0) = 0x7f3a2c1d0000
close(3) = 0
openat(AT_FDCWD, "/lib/x86_64-linux-gnu/libc.so.6", O_RDONLY|O_CLOEXEC) = 3
read(3, "\177ELF\2\1\1\3...", 832) = 832
mmap(NULL, 2037344, PROT_READ, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0x7f3a...
close(3) = 0
getdents64(3, /* 12 entries */, 32768) = 336
write(1, "file1.txt file2.log\n", 21) = 21
close(1) = 0
exit_group(0) = ?
Syscall satırı formatı
| Bileşen | Örnek | Açıklama |
|---|---|---|
| Syscall adı | openat | Çağrılan kernel fonksiyonu |
| Argümanlar | AT_FDCWD, "/etc/ld.so.cache", O_RDONLY|O_CLOEXEC | Syscall parametreleri, string olarak decode edilmiş |
| Dönüş değeri | = 3 | Başarıda fd numarası, hata durumunda -1 |
| Hata kodu | = -1 ENOENT (No such file or directory) | Sadece hata durumunda görünür |
-c özet çıktısı
strace -c ls /tmp
% time seconds usecs/call calls errors syscall
------ ----------- ----------- --------- --------- ----------------
38.21 0.000412 41 10 mmap
22.14 0.000239 29 8 openat
14.87 0.000160 22 7 read
8.92 0.000096 13 7 fstat
5.43 0.000058 14 4 close
4.11 0.000044 11 4 mprotect
3.72 0.000040 13 3 brk
2.60 0.000028 28 1 getdents64
------ ----------- ----------- --------- --------- ----------------
100.00 0.001077 44 0 total
Filtreleme ve zamanlama seçenekleri
openat(...) = 3 <0.000042># Sadece network syscall'ları, süre ile
strace -T -e trace=network curl https://example.com 2>&1 | head -15
Bu bölümde öğrendikleriniz
- strace, ptrace() ile her syscall'ı girişte ve çıkışta yakalar
- Çıktı formatı:
syscall(argümanlar) = dönüş -cile istatistiksel özet,-e trace=ile filtreleme,-Tile süre ölçümü yapılır
02 strace gelişmiş kullanım
Child process takibi, çalışan process'e attach, çıktıyı dosyaya yönlendirme ve fd çözümleme — strace'in gerçek gücü bu seçeneklerde.
-f: child process'leri takip et
Fork veya exec yapan uygulamalarda -f olmadan sadece parent process görülür. Shell script'leri, daemon'lar veya system() çağrısı yapan programlarda -f şarttır.
# bash + fork + exec zincirini takip et
strace -f bash -c "ls /tmp && cat /etc/hostname"
# Her satırın başına PID ekle (çok process varsa şart)
strace -f -e trace=execve -o /tmp/trace.txt ./myapp
-p PID: çalışan process'e attach
# PID bul
pidof nginx
# Çalışan process'e attach
strace -p 1234
# Tüm nginx worker'larını izle (-f ile birlikte)
strace -f -p 1234 -e trace=network 2>&1 | head -50
Process'e attach etmek için root yetkisi veya CAP_SYS_PTRACE capability gerekir. Modern Linux sistemlerinde /proc/sys/kernel/yama/ptrace_scope = 1 ise sadece child process'lere attach edilebilir; bunu sudo sysctl kernel.yama.ptrace_scope=0 ile geçici olarak değiştirebilirsiniz.
-o: çıktıyı dosyaya yönlendir
# Çıktıyı dosyaya yaz (stderr yerine)
strace -o /tmp/strace.log ./myapp
# -f ile çok process: her process ayrı dosyaya (PID eklenir)
strace -f -o /tmp/trace ./myapp
# → /tmp/trace.1234, /tmp/trace.1235, ...
-s: string uzunluğunu artır
strace, varsayılan olarak string argümanları 32 karakterde keser. Config dosya yolları, HTTP başlıkları veya uzun path'leri görmek için bu değeri artırın.
# Default: 32 karakter (path'ler kesilir)
strace ./myapp
# openat(AT_FDCWD, "/etc/myapp/config/application.co"..., O_RDONLY) = -1
# -s 256 ile tam path
strace -s 256 ./myapp
# openat(AT_FDCWD, "/etc/myapp/config/application.conf", O_RDONLY) = -1 ENOENT
-y ve -yy: fd'leri çözümle
# -y: fd numarasını dosya adına çevir
strace -y ./myapp
# read(3</etc/passwd>, ...) — fd 3'ün /etc/passwd olduğu görünür
# -yy: socket fd'lerini adres:port olarak göster
strace -yy ./myapp
# sendto(5<TCP:127.0.0.1:8080->10.0.0.1:443>, ...)
Gerçek senaryo: "config dosyası neden yüklenmiyor?"
Uygulama başlıyor, hata mesajı veriyor ama hangi dosyayı aradığını söylemiyor. strace ile 30 saniyede çözülür:
# 1. Sadece dosya açma hataları filtrele
strace -e trace=openat,open -s 256 ./myapp 2>&1 \
| grep ENOENT
# Çıktı:
# openat(AT_FDCWD, "/etc/myapp.conf", O_RDONLY) = -1 ENOENT
# openat(AT_FDCWD, "/home/user/.config/myapp.conf", O_RDONLY) = -1 ENOENT
# → Program /etc/myapp.conf'u arıyor, dosya mevcut değil
# 2. Çözüm: doğru path'e semlink veya dosya oluştur
sudo cp myapp.conf.example /etc/myapp.conf
Bu bölümde öğrendikleriniz
-file fork/exec zincirinin tamamı takip edilir-p PIDile çalışan sürece attach edilir-s 256 -y -yykombinasyonu ile tam dosya yolları ve socket adresleri görülür- Config yükleme sorunları strace ile dakikalar içinde tespit edilir
03 ltrace: kütüphane çağrıları
ltrace, syscall'ların bir seviye üstünde çalışır: dinamik olarak bağlanan kütüphane fonksiyonlarını (libc, libssl, libcurl…) yakalar.
ltrace nedir?
strace kernel-user boundary'yi izlerken ltrace, shared library'lerin PLT (Procedure Linkage Table) girdilerini hook eder. Bu sayede malloc(), fopen(), SSL_connect() gibi libc ve üst seviye kütüphane çağrıları görülür — bunlar doğrudan syscall değildir.
ltrace ls /tmp 2>&1 | head -20
__libc_start_main(0x401b20, 2, 0x7ffd..., ...) = 0
setlocale(LC_ALL, "") = "en_US.UTF-8"
bindtextdomain("coreutils", "/usr/share/locale") = "/usr/share/locale"
textdomain("coreutils") = "coreutils"
__cxa_atexit(0x40a480, 0, 0x603260) = 0
isatty(1) = 1
malloc(40) = 0x604670
opendir("/tmp") = 0x6046b0
readdir(0x6046b0) = 0x6046f0
free(0x604670) = <void>
strace vs ltrace karşılaştırması
| Özellik | strace | ltrace |
|---|---|---|
| Hook noktası | Kernel syscall arayüzü | Shared library PLT |
| Ne yakalar? | read, write, openat, socket… | malloc, fopen, strcmp, SSL_connect… |
| Static binary | Çalışır | Çalışmaz |
| Performans overhead | Yüksek | Yüksek |
| Kullanım amacı | OS etkileşimi, hata kodları | Kütüphane çağrısı profilleme |
Filtreleme seçenekleri
# Özet istatistik
ltrace -c ./myapp
# Sadece malloc ve free çağrıları
ltrace -e malloc+free ./myapp
# Belirli bir kütüphaneyi izle
ltrace -l libssl.so.3 openssl s_client -connect example.com:443
# Child process'leri de takip et
ltrace -f ./myapp
ltrace yalnızca dinamik olarak bağlanmış binary'lerde çalışır. gcc -static ile derlenen veya Go gibi statik binary üreten derleyicilerle oluşturulan programlarda ltrace hiçbir çıktı üretmez. Bunu file ./myapp ile kontrol edin: "dynamically linked" yazıyorsa ltrace çalışır.
Bu bölümde öğrendikleriniz
- ltrace, shared library PLT'yi hook ederek kütüphane çağrılarını yakalar
- strace kernel sınırını, ltrace kütüphane sınırını görür — ikisi birbirini tamamlar
- Static binary'lerde ltrace çalışmaz;
filekomutu ile binary türü kontrol edilmelidir
04 perf stat: CPU counter'ları
perf, CPU'nun içindeki donanım sayaçlarını (PMU) okuyarak instructions, cycles, cache miss ve branch misprediction sayılarını gerçek zamanlı olarak raporlar.
PMU nedir?
Modern CPU'lar, Performance Monitoring Unit (PMU) adı verilen donanım devrelerine sahiptir. Bu devreler her clock cycle'da belirli olayları sayar: kaç instruction çalıştırıldı, kaç L1/L2/LLC cache miss yaşandı, kaç branch prediction yanlış gitti. perf, bu sayaçları root yetkisi olmadan ve çok düşük overhead ile okur.
perf stat: temel kullanım
perf stat ./myapp
Performance counter stats for './myapp':
1,842.53 msec task-clock # 0.998 CPUs utilized
4 context-switches # 2.171 /sec
0 cpu-migrations # 0.000 /sec
512 page-faults # 277.857 /sec
4,921,034,128 cycles # 2.671 GHz
6,284,019,442 instructions # 1.28 insn per cycle ← IPC
847,234,891 branches # 459.788 M/sec
3,421,023 branch-misses # 0.40% of all branches
1.845761234 seconds time elapsed
1.840123000 seconds user
0.004534000 seconds sys
IPC: Instructions Per Cycle
IPC değeri uygulamanın CPU'yu ne kadar verimli kullandığını gösterir:
| IPC Değeri | Yorum | Muhtemel Neden |
|---|---|---|
| < 0.5 | Çok kötü | Memory-bound: L2/L3/DRAM bekleniyor |
| 0.5 – 1.0 | Zayıf | Cache miss veya branch mispredict |
| 1.0 – 2.0 | Normal | Tipik uygulama aralığı |
| > 3.0 | Mükemmel | Vektörizasyon, SIMD, pipeline doldu |
Özel event'lerle detay ölçümü
# Cache miss detayı
perf stat -e cache-misses,cache-references,LLC-loads,LLC-load-misses ./myapp
# Mevcut event listesi
perf list | grep cache
# 5 kez çalıştır, ortalama ve standart sapma hesapla
perf stat -r 5 ./myapp
1.847213534 seconds time elapsed ( +- 0.23% )
1.841890200 seconds user ( +- 0.24% )
0.005230600 seconds sys ( +- 1.12% )
perf top: canlı CPU profil
# Tüm sistem genelinde CPU yiyen fonksiyonlar (htop gibi ama fonksiyon bazlı)
sudo perf top
# Belirli bir process
sudo perf top -p $(pidof myapp)
# Call-graph ile (hangi fonksiyon kimi çağırıyor)
sudo perf top -g
Bu bölümde öğrendikleriniz
- PMU, donanım seviyesinde düşük overhead ile CPU metriklerini sayar
- IPC değeri CPU verimliliğinin temel göstergesidir; düşük IPC → memory-bound veya cache miss sorunu
perf stat -r 5ile istatistiksel doğruluk sağlanır;perf topile canlı hotspot görülür
05 perf record/report ve flamegraph
perf record, örnekleme tabanlı profil kaydeder; perf report ve FlameGraph ile zaman harcayan fonksiyonlar call-graph'ıyla görselleştirilir.
perf record: profil kayıt
# -g: call-graph (backtrace) kaydet — flamegraph için şart
perf record -g ./myapp
# Çalışan process'e attach
sudo perf record -g -p $(pidof myapp) -- sleep 10
# Frekans ayarla (Hz): default 4000, daha az overhead için düşür
perf record -F 99 -g ./myapp
# → perf.data dosyası oluşturulur
ls -lh perf.data
perf report: interaktif TUI
# İnteraktif TUI (ok tuşlarıyla gezin, Enter ile aç)
perf report
# Text çıktı (pipe veya CI için)
perf report --stdio 2>&1 | head -40
# Belirli bir sembol için assembly annotation
perf annotate main --stdio
# Overhead Command Shared Object Symbol
# ........ ........ ................ ......................
#
42.31% myapp myapp [.] process_buffer
18.74% myapp libc.so.6 [.] __memcpy_avx_unaligned
9.12% myapp myapp [.] parse_header
7.03% myapp myapp [.] hash_lookup
4.21% myapp [kernel] [k] __get_user_pages
FlameGraph üretme
# Brendan Gregg'in FlameGraph araçlarını indir
git clone https://github.com/brendangregg/FlameGraph /opt/flamegraph
# Profil kaydet
perf record -F 99 -g -p $(pidof myapp) -- sleep 30
# SVG üret
perf script \
| /opt/flamegraph/stackcollapse-perf.pl \
| /opt/flamegraph/flamegraph.pl > /tmp/flame.svg
# Tarayıcıda aç
xdg-open /tmp/flame.svg
FlameGraph okuma rehberi
| Boyut / Renk | Anlamı |
|---|---|
| Yatay genişlik | O fonksiyonun toplam CPU zamanındaki oranı — en geniş bar en fazla CPU alan fonksiyon |
| Dikey yükseklik | Call stack derinliği — en altta çağıran, en üstte çağrılan |
| Renk | Anlamsız — sadece okunabilirlik için rastgele seçilir |
| Düz plato (geniş + yatay tavan) | O fonksiyon çok zaman harcıyor ve çocuklarına dağıtmıyor → hotspot |
FlameGraph anlamlı sonuç vermesi için binary'nin sembol tablosunu içermesi gerekir: -g flag'iyle derleme yapın (gcc -O2 -g myapp.c). strip edilmiş binary'lerde fonksiyon adları yerine hex adres görülür.
Bu bölümde öğrendikleriniz
perf record -gcall-graph bilgisiyle örnekleme profili kaydederperf report --stdiotext çıktı verir; interaktif TUI ile call stack gezilir- FlameGraph'ta en geniş plateau → CPU hotspot; renk anlamsızdır
06 valgrind memcheck
valgrind, uygulamayı sentetik bir CPU üzerinde çalıştırarak her bellek erişimini izler — leak, invalid access ve double free hatalarını stack trace ile raporlar.
Çalışma modeli
valgrind, hedef binary'yi JIT ile kendi sanal CPU'suna çevirir. Her malloc()/free() ve her bellek okuma/yazma işlemi izlenir. Bu yüzden overhead yüksektir (2–10x yavaş), ancak başka hiçbir araç onun yakaladığı hataları bu kesinlikte yakalayamaz.
Temel kullanım
# Tam leak analizi
valgrind --leak-check=full --show-leak-kinds=all \
--track-origins=yes -v ./myapp 2>&1 | tee valgrind.log
Leak türleri
| Tür | Açıklama | Öncelik |
|---|---|---|
| definitely lost | Hiçbir pointer bu bloğa işaret etmiyor — kesin leak | Kritik |
| indirectly lost | "Definitely lost" bir bloktan ulaşılan başka bloklar | Yüksek |
| possibly lost | Pointer var ama bloğun başına değil ortasına işaret ediyor | Orta |
| still reachable | Program sonunda hâlâ erişilebilir pointer var (program sonunda free edilmemiş) | Düşük |
Gerçek bug: heap-use-after-free
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
int main(void) {
char *buf = malloc(64);
strcpy(buf, "merhaba");
free(buf); /* buf serbest bırakıldı */
/* HATA: free sonrası erişim — use-after-free */
printf("%s\n", buf);
return 0;
}
==12345== Invalid read of size 1
==12345== at 0x4C33A22: strlen (vg_replace_strmem.c:459)
==12345== at 0x1091C5: main (uaf-bug.c:12)
==12345== Address 0x5204040 is 0 bytes inside a block of size 64 free'd
==12345== at 0x4C30D3B: free (vg_replace_malloc.c:530)
==12345== at 0x1091BE: main (uaf-bug.c:9)
==12345== Block was alloc'd at
==12345== at 0x4C2FB0F: malloc (vg_replace_malloc.c:309)
==12345== at 0x10918B: main (uaf-bug.c:6)
==12345==
==12345== LEAK SUMMARY:
==12345== definitely lost: 0 bytes in 0 blocks
==12345== indirectly lost: 0 bytes in 0 blocks
==12345== possibly lost: 0 bytes in 0 blocks
==12345== still reachable: 0 bytes in 0 blocks
Suppression dosyası
{
openssl_false_positive
Memcheck:Leak
match-leak-kinds: reachable
fun:malloc
obj:*libcrypto*
}
valgrind --suppressions=my.supp --leak-check=full ./myapp
Bu bölümde öğrendikleriniz
- valgrind, sentetik CPU üzerinde her bellek erişimini izler — overhead yüksektir ama hata tespiti çok doğrudur
- "Definitely lost" kesin leak; "still reachable" genellikle düşük öncelikli
- Stack trace ile hatanın tam satırı ve allocation noktası gösterilir
- Suppression dosyası ile kütüphane kaynaklı false positive'ler bastırılır
07 AddressSanitizer (ASan)
ASan, compiler instrumentation ile çalışır — valgrind'den yaklaşık 2x daha hızlı, ancak derleme zamanında aktif edilmesi gerekir.
ASan nedir?
AddressSanitizer, LLVM/Clang ekibinin geliştirdiği ve GCC'nin de desteklediği bir compiler instrumentation aracıdır. Derleme sırasında her bellek erişiminin yanına kontrol kodu eklenir (shadow memory yöntemi). Valgrind gibi sanal bir CPU gerektirmediğinden overhead çok daha düşüktür.
Derleme ve çalıştırma
# ASan + sembol için -g şart
gcc -fsanitize=address -g -O1 uaf-bug.c -o myapp-asan
# Derleme sonrası normal gibi çalıştır
./myapp-asan
==12346==ERROR: AddressSanitizer: heap-use-after-free on address 0x602000000010
READ of size 1 at 0x602000000010 thread T0
#0 0x401234 in strlen /usr/include/string.h:395
#1 0x401456 in main uaf-bug.c:12
#2 0x7f3a2b main in libc-start.c
0x602000000010 is located 0 bytes inside of 64-byte region
FREED by thread T0 here:
#0 0x7f3a2b in __interceptor_free sanitizer_common_interceptors.inc:752
#1 0x4013e2 in main uaf-bug.c:9
ALLOCATED by thread T0 here:
#0 0x7f3a2b in __interceptor_malloc sanitizer_common_interceptors.inc:823
#1 0x401378 in main uaf-bug.c:6
Shadow bytes around the buggy address:
0x0c047fff7fb0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x0c047fff7fc0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
=>0x0c047fff7fd0:[fd]fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd
Sanitizer ailesi
# ASan + UBSan kombinasyonu (yaygın CI konfigürasyonu)
gcc -fsanitize=address,undefined -g -O1 myapp.c -o myapp-san
# TSan ayrı derlenmeli
gcc -fsanitize=thread -g -O1 myapp.c -o myapp-tsan
ASan ve diğer sanitizer'larla derlenmiş binary'leri asla production ortamında çalıştırmayın. Shadow memory için ~2x fazla RAM kullanırlar, overhead 1.5–2x düzeyindedir ve bazı sanitizer'lar (TSan) 5–15x overhead getirir. Bu araçlar yalnızca test ve CI pipeline'ları içindir.
Bu bölümde öğrendikleriniz
- ASan, compiler instrumentation ile çalışır — valgrind'den 2x hızlı, derleme zamanında aktif edilir
- ASan + UBSan kombinasyonu çoğu bug türünü tek derlemede yakalar
- TSan, ASan ile aynı anda kullanılamaz; ayrı derleme gerekir
- Sanitizer'lar sadece test/CI ortamında kullanılmalıdır
08 Pratik debug senaryoları
Gerçek dünya sorunları ve bu araçları sistematik olarak nasıl zincirleyeceğiniz — dört klasik senaryo.
Senaryo 1: "Uygulama açılmıyor"
Binary çalışıyor ama hemen çıkıyor, hata mesajı belirsiz. Önce shared library eksikliğini kontrol et, ardından config dosyası sorununu araştır.
# 1. Shared library bağımlılıkları kontrol
ldd ./myapp
# → "libmylib.so.2 => not found" varsa sorun bu
# 2. strace ile tam başlangıç izle
strace -e trace=openat,open,read -s 256 ./myapp 2>&1 | grep -E "ENOENT|EACCES"
# Tipik çıktı:
# openat(AT_FDCWD, "/etc/myapp/myapp.conf", O_RDONLY) = -1 ENOENT
# → Config dosyası eksik
# 3. execve başarısız oluyorsa
strace -e trace=execve ./myapp 2>&1
# execve("/usr/bin/myapp", ...) = -1 EACCES → execute izni yok
chmod +x ./myapp
Senaryo 2: "Memory yavaş yavaş artıyor"
# 1. Hızlı kontrol: RSS artışını izle
while true; do
cat /proc/$(pidof myapp)/status | grep VmRSS
sleep 5
done
# 2. smaps ile hangi mapping büyüyor?
cat /proc/$(pidof myapp)/smaps | grep -A 1 heap
# 3. valgrind ile leak tespiti (test ortamında)
valgrind --leak-check=full --track-origins=yes \
--log-file=leak.log ./myapp &
sleep 60
kill %1
grep "definitely lost" leak.log
Senaryo 3: "Yüksek CPU"
# 1. Hangi fonksiyon CPU yiyor? (canlı)
sudo perf top -p $(pidof myapp)
# 2. 30 saniye profil al
sudo perf record -F 99 -g -p $(pidof myapp) -- sleep 30
# 3. Flamegraph üret
perf script | /opt/flamegraph/stackcollapse-perf.pl \
| /opt/flamegraph/flamegraph.pl > /tmp/cpu-flame.svg
# 4. Text rapor (en pahalı 10 fonksiyon)
perf report --stdio --sort overhead | head -20
Senaryo 4: "Segfault"
# 1. Core dump aktif et
ulimit -c unlimited
echo "/tmp/core.%p" | sudo tee /proc/sys/kernel/core_pattern
# 2. Uygulamayı çalıştır (crash olsun)
./myapp
# Segmentation fault (core dumped)
# 3. gdb ile core analiz
gdb ./myapp /tmp/core.$(pidof myapp 2>/dev/null || echo "*")
# gdb prompt:
# (gdb) bt ← backtrace
# (gdb) bt full ← tüm yerel değişkenler
# (gdb) info locals ← mevcut frame değişkenleri
# (gdb) frame 2 ← call stack'te 2. frame'e git
# 4. Alternatif: ASan ile yeniden derle (stack trace daha açık)
gcc -fsanitize=address -g -O1 myapp.c -o myapp-asan && ./myapp-asan
Debug araçları zinciri
Sorun bildir
│
├─ "Açılmıyor / hata"
│ └─ ldd → strace -e file,network -s256 → grep ENOENT/EACCES
│
├─ "Segfault / crash"
│ └─ ulimit -c unlimited → gdb + core → bt full
│ veya gcc -fsanitize=address → ASan output
│
├─ "Yüksek CPU"
│ └─ perf top → perf record -g → flamegraph → hotspot
│
└─ "Memory artıyor"
└─ /proc/PID/status VmRSS → smaps
valgrind --leak-check=full → definitely lost
ya da gcc -fsanitize=address,leak
Bu bölümde öğrendikleriniz
- "Uygulama açılmıyor" →
ldd+strace -e file -s256 | grep ENOENT - "Memory artıyor" →
/proc/PID/status+valgrind --leak-check=full - "Yüksek CPU" →
perf top+perf record -g+ flamegraph - "Segfault" → core dump +
gdbbacktrace veya ASan ile yeniden derleme