Geliştirici Araçları
TEKNİK REHBER GELİŞTİRİCİ ARAÇLARI BİNUTILS 2026

readelf —
ELF anatomisi.

Magic bytes'tan program header'a, NEEDED bağımlılıklarından relocation tablosuna — ELF dosyasının her katmanını readelf ile incele. Shared library analizi ve stripped binary debug.

00 ELF format anatomy — magic bytes ve yapı

ELF (Executable and Linkable Format), Linux'ta çalıştırılabilir dosyalar, shared library'ler (.so) ve nesne dosyaları (.o) için standart ikili formattır. readelf bu formatı human-readable şekilde sunar.

Her ELF dosyası ELF header ile başlar (52 bayt 32-bit, 64 bayt 64-bit). Ardından isteğe bağlı olarak program header tablosu (runtime loader için) ve section header tablosu (linker için) gelir. Bu iki tablo birbirinden bağımsızdır: çalıştırılabilir dosyalarda ikisi de bulunur, paylaşımlı kütüphanelerde ikisi de, .o dosyalarında yalnızca section header tablosu vardır.

Magic bytes — her ELF dosyasının ilk 4 baytı

bash
# xxd ile ilk 16 bayta bak
xxd myapp | head -1
# 00000000: 7f45 4c46 0101 0100 0000 0000 0000 0000  .ELF............
# ^^^^^^^   7f 'E' 'L' 'F' = Magic
# Byte 4: 01=32-bit, 02=64-bit
# Byte 5: 01=little-endian, 02=big-endian
# Byte 6: ELF version (her zaman 1)
NEDEN readelf, objdump DEĞİL?

readelf yalnızca ELF formatını okur; BFD (Binary File Descriptor) kütüphanesini kullanmaz. Bu nedenle objdump'tan daha güvenilir ve deterministtir — özellikle alışılmadık ELF dosyalarında. Ayrıca readelf her zaman ham ELF görünümünü sunarken objdump bazen soyutlama ekler.

01 -h — file header

ELF file header, dosyanın türü, hedef mimarisi, entry point adresi ve header tablosu konumları gibi temel meta verileri içerir.

bash
readelf -h myapp
readelf -h çıktısı (ARM 32-bit)
ELF Header:
  Magic:   7f 45 4c 46 01 01 01 00 00 00 00 00 00 00 00 00
  Class:                             ELF32
  Data:                              2's complement, little endian
  Version:                           1 (current)
  OS/ABI:                            UNIX - System V
  ABI Version:                       0
  Type:                              EXEC (Executable file)
  Machine:                           ARM
  Version:                           0x1
  Entry point address:               0x10455
  Start of program headers:          52 (bytes into file)
  Start of section headers:          28916 (bytes into file)
  Flags:                             0x5000400, Version5 EABI, hard-float ABI
  Size of this header:               52 (bytes)
  Size of program headers:           32 (bytes)
  Number of program headers:         9
  Size of section headers:           40 (bytes)
  Number of section headers:         30
  Section header string table index: 29

Önemli alanlar

Type
EXEC (çalıştırılabilir), DYN (shared lib veya PIE), REL (object dosyası), CORE (core dump)
Machine
ARM, AArch64, x86-64 vb. Cross-compile doğrulaması için kontrol edilir.
Entry point address
Kernel'ın kontrolü devreteceği ilk adres. ARM'da tek numaralı adres = Thumb mode başlangıcı.
Flags
ARM'da EABI versiyonu ve FPU tipi (hard-float/soft-float) burada görünür. Yanlış ABI karışımı runtime hatasına yol açar.

02 -S — section headers (flags: AX, WA)

Section header tablosu, linker'ın ve debug araçlarının kullandığı mantıksal bölümleri listeler. Her section'ın adresi, boyutu ve flag'leri mevcuttur.

bash
readelf -S myapp
# Geniş çıktı için --wide ekle
readelf -SW myapp
readelf -S çıktısı
There are 30 section headers, starting at offset 0x70f4:

Section Headers:
  [Nr] Name              Type            Addr     Off    Size   ES Flg Lk Inf Al
  [ 0]                   NULL            00000000 000000 000000 00      0   0  0
  [ 1] .interp           PROGBITS        00010154 000154 000013 00   A  0   0  1
  [ 2] .note.ABI-tag     NOTE            00010168 000168 000020 00   A  0   0  4
  [ 3] .text             PROGBITS        00010454 000454 003a4c 00  AX  0   0  4
  [ 4] .rodata           PROGBITS        00013ea0 003ea0 0004f8 00   A  0   0  4
  [ 5] .data             PROGBITS        00020000 004000 000124 00  WA  0   0  4
  [ 6] .bss              NOBITS          00020124 004124 0008a0 00  WA  0   0  8
  [ 7] .debug_info       PROGBITS        00000000 004124 012345 00      0   0  1
  [ 8] .symtab           SYMTAB          00000000 0164c0 001234 10     29  50  4
  [ 9] .strtab           STRTAB          00000000 0176f4 000890 00      0   0  1

Flag anlamları

A (ALLOC)
Çalışma zamanında bellek tahsis edilir. .interp, .text, .data, .bss hepsi A flag'lidir.
X (EXECINSTR)
Çalıştırılabilir talimatlar içerir. .text ve benzeri kod section'ları AX flag'lidir.
W (WRITE)
Yazılabilir section. .data ve .bss WA flag'lidir. .text asla W olmamalı (güvenlik).
NOBITS
.bss tipi: dosyada yer kaplamaz, sadece boyutu bilinir; başlatma sırasında sıfırlanır.

03 -l — program headers (LOAD / PT_DYNAMIC)

Program header tablosu, runtime loader'ın (ld.so) dosyayı belleğe nasıl yükleyeceğini tanımlar. Section header'lardan farklı olarak çalışma zamanına yöneliktir.

bash
readelf -l myapp
readelf -l çıktısı
Elf file type is EXEC (Executable file)
Entry point 0x10455
There are 9 program headers, starting at offset 52

Program Headers:
  Type           Offset   VirtAddr   PhysAddr   FileSiz  MemSiz   Flg Align
  PHDR           0x000034 0x00010034 0x00010034 0x00120  0x00120  R   0x4
  INTERP         0x000154 0x00010154 0x00010154 0x00013  0x00013  R   0x1
      [Requesting program interpreter: /lib/ld-linux-armhf.so.3]
  LOAD           0x000000 0x00010000 0x00010000 0x043f8  0x043f8  R E 0x10000
  LOAD           0x004000 0x00020000 0x00020000 0x00124  0x009c4  RW  0x10000
  DYNAMIC        0x004000 0x00020000 0x00020000 0x000f8  0x000f8  RW  0x4
  NOTE           0x000168 0x00010168 0x00010168 0x00044  0x00044  R   0x4
  GNU_STACK      0x000000 0x00000000 0x00000000 0x00000  0x00000  RW  0x10
  GNU_RELRO      0x004000 0x00020000 0x00020000 0x00100  0x00100  R   0x1
  ARM_EXIDX      0x003ea0 0x00013ea0 0x00013ea0 0x000b8  0x000b8  R   0x4

Segment tipleri

INTERP
Dinamik linker yolu: /lib/ld-linux-armhf.so.3. Statik binary'lerde bu segment yoktur.
LOAD
Dosyadan belleğe yüklenen segment. FileSiz ≠ MemSiz ise aradaki fark sıfırlanır (.bss).
DYNAMIC
Dinamik bağlama bilgileri: NEEDED listesi, GOT/PLT adresleri.
GNU_STACK
Stack çalıştırılabilirlik bayrağı. RW = güvenli, RWE = tehlikeli (NX ihlali).
ARM_EXIDX
ARM'a özgü exception unwind tablosu. Stack backtrace için gereklidir.

04 -s — symbol tables

readelf -s hem statik sembol tablosunu (.symtab) hem de dinamik sembol tablosunu (.dynsym) gösterir.

bash
# Her iki sembol tablosu
readelf -s myapp

# Sadece dinamik semboller (strip sonrası da kalır)
readelf --dyn-syms myapp

# Belirli bir sembolü ara
readelf -s myapp | grep "sensor_read"
readelf -s çıktısı
Symbol table '.symtab' contains 156 entries:
   Num:    Value  Size Type    Bind   Vis      Ndx Name
     0: 00000000     0 NOTYPE  LOCAL  DEFAULT  UND
     1: 00010154     0 SECTION LOCAL  DEFAULT    1
    48: 00010454    60 FUNC    LOCAL  DEFAULT    3 main
    49: 00010490   168 FUNC    GLOBAL DEFAULT    3 sensor_read
    50: 00020000     4 OBJECT  GLOBAL DEFAULT    5 g_sensor_value
    51: 00000000     0 FUNC    GLOBAL DEFAULT  UND printf
    52: 00000000     0 FUNC    GLOBAL DEFAULT  UND __libc_start_main

Symbol table '.dynsym' contains 12 entries:
   Num:    Value  Size Type    Bind   Vis      Ndx Name
     0: 00000000     0 NOTYPE  LOCAL  DEFAULT  UND
     1: 00000000     0 FUNC    GLOBAL DEFAULT  UND printf@GLIBC_2.4
     2: 00010490   168 FUNC    GLOBAL DEFAULT    3 sensor_read

.dynsym, dinamik bağlama sırasında çözülecek sembolleri içerir ve strip sonrası da korunur. .symtab ise tüm sembolleri içerir; strip komutu bunu kaldırır.

05 -d — dynamic section (NEEDED / SONAME / RPATH)

Dynamic section, çalışma zamanında dinamik linker'ın ihtiyaç duyduğu tüm bilgileri içerir: bağımlı kütüphaneler, arama yolları, sembol tablosu adresleri.

bash
readelf -d myapp
readelf -d çıktısı
Dynamic section at offset 0x4000 contains 26 entries:
  Tag        Type                         Name/Value
 0x00000001 (NEEDED)                     Shared library: [libpthread.so.0]
 0x00000001 (NEEDED)                     Shared library: [libm.so.6]
 0x00000001 (NEEDED)                     Shared library: [libc.so.6]
 0x0000000e (SONAME)                     Library soname: [libmysensor.so.1]
 0x0000000f (RPATH)                      Library rpath: [/opt/sysroot/arm-linux-gnueabihf/lib]
 0x00000005 (STRTAB)                     0x10230
 0x00000006 (SYMTAB)                     0x101b0
 0x0000000a (STRSZ)                      312 (bytes)
 0x0000000b (SYMENT)                     16 (bytes)
 0x00000015 (DEBUG)                      0x0
 0x00000003 (PLTGOT)                     0x20090
 0x00000002 (PLTRELSZ)                   64 (bytes)
 0x00000017 (JMPREL)                     0x103a8
 0x00000000 (NULL)                       0x0

Kritik tag'ler

NEEDED
Çalışma zamanında gereken shared library. Birden fazla NEEDED girdisi olabilir. Eksik kütüphane "not found" hatasına yol açar.
SONAME
Bu kütüphanenin kendine verdiği isim. libfoo.so.1.2.3 dosyası libfoo.so.1 SONAME'iyle yayınlanabilir.
RPATH / RUNPATH
Embedded sistemlerde sıkça kullanılan hardcoded kütüphane arama yolu. Cross-compile sysroot'u işaret eder. Güvenlik açısından dikkatli kullanılmalı.

06 -r — relocations

Relocation tablosu, linker'ın veya dinamik yükleyicinin çözümlemesi gereken sembol referanslarını listeler.

bash
# Tüm relocation'ları göster
readelf -r myapp

# Object dosyasındaki relocation'lar
readelf -r main.o
readelf -r çıktısı
Relocation section '.rel.plt' at offset 0x3a8 contains 4 entries:
 Offset     Info    Type            Sym.Value  Sym. Name
00020090  00000116 R_ARM_JUMP_SLOT   00000000   printf
00020094  00000216 R_ARM_JUMP_SLOT   00000000   malloc
00020098  00000316 R_ARM_JUMP_SLOT   00000000   free
0002009c  00000416 R_ARM_JUMP_SLOT   00000000   __libc_start_main

Relocation section '.rel.dyn' at offset 0x3c8 contains 2 entries:
 Offset     Info    Type            Sym.Value  Sym. Name + Addend
00020004  00000115 R_ARM_GLOB_DAT    00000000   __gmon_start__

R_ARM_JUMP_SLOT: PLT (Procedure Linkage Table) girişleri — lazy binding için. R_ARM_GLOB_DAT: GOT (Global Offset Table) girişleri — global değişkenler için.

07 Pratik: shared lib bağımlılık analizi + stripped binary

Embedded sistemde yaygın iki senaryo: "hangi shared library'lere bağımlı?" ve "strip edilmiş binary'de sembol var mı?"

Senaryo 1: shared library bağımlılık ağacı

bash
# Doğrudan bağımlılıkları listele
readelf -d /usr/bin/python3 | grep NEEDED
# (NEEDED) libpthread.so.0
# (NEEDED) libdl.so.2
# (NEEDED) libutil.so.1
# (NEEDED) libm.so.6
# (NEEDED) libc.so.6

# ldd ile tüm transitif bağımlılıklar (sysroot ile çalışmaz!)
ldd /usr/bin/python3

# Cross ARM için: sysroot içindeki binary
readelf -d /opt/sysroot/usr/bin/myapp | grep -E "NEEDED|RPATH|RUNPATH"

# Rootfs'te eksik kütüphane tespiti
SYSROOT=/path/to/rootfs
readelf -d "$SYSROOT/usr/bin/myapp" | grep NEEDED | \
  awk '{print $5}' | tr -d '[]' | while read lib; do
    find "$SYSROOT" -name "$lib" 2>/dev/null || echo "EKSİK: $lib"
  done

Senaryo 2: stripped binary'de sembol durumu

bash
# Strip edilmiş mi? file komutu ile kontrol
file /usr/bin/ls
# ELF 64-bit LSB pie executable, x86-64, ..., stripped

# readelf ile sembol tablosu durumu
readelf -S /usr/bin/ls | grep -E "symtab|dynsym"
# [11] .dynsym  DYNSYM  ... (strip sonrası hâlâ mevcut)
# .symtab yoktur — strip kaldırdı

# Dinamik semboller hâlâ görülebilir
readelf --dyn-syms /usr/bin/ls | head -20

# ELF version bilgisi (GLIBC_2.x bağımlılığı)
readelf -V /usr/bin/ls
# Version needs section '.gnu.version_r' ...
# GLIBC_2.34 (libc.so.6)
# GLIBC_2.33 (libc.so.6)

# Embedded hedef farklı GLIBC sürümü kullanıyorsa çakışma yaşanır!
# Çözüm: musl libc, statik derleme veya sysroot ile uyumlu cross-compile

ARM ABI kontrolü

bash
# Hard-float / soft-float karışımı sorun yaratır
readelf -h libsensor.so | grep Flags
# Flags: 0x5000400, Version5 EABI, hard-float ABI

readelf -h myapp | grep Flags
# Flags: 0x5000200, Version5 EABI, soft-float ABI  <-- UYUMSUZ!

# Doğru eşleşme: her ikisi de hard-float veya her ikisi de soft-float olmalı
# ARM hard-float: -mfloat-abi=hard, -mfpu=neon-vfpv4
# ARM soft-float: -mfloat-abi=soft veya softfp