ELF-Sektion: .meta_safe

Die .meta_safe-Sektion ist eine feste Datenstruktur innerhalb der ELF64-Binärdatei, die der Lyx-Compiler automatisch erzeugt, wenn eine Unit mit @integrity annotiert ist. Sie ist die Vertrauensverankerung für den Memory-Scrubbing-Mechanismus und den TMR-Mehrheitsentscheid über die Code-Referenzhashes.

→ Verwandt: Memory Scrubbing · TMR · DO-178C Hauptseite


1. Gesamtstruktur (8232 Byte)

Die Sektion hat eine feste Größe von 8232 Byte. Die drei CRC32-Hashes liegen jeweils 4096 Byte voneinander entfernt — eine Standard-Speicherseite auf den meisten Architekturen. Ein lokaler Speicherdefekt (fehlerhafte Speicherzeile, Hot-Bit) kann dadurch nicht zwei Hashes gleichzeitig korrumpieren.

Offset       Größe    Feld               Typ        Beschreibung
─────────────────────────────────────────────────────────────────────────
0x0000       8 B      code_start_va      uint64 LE  Virtuelle Startadresse des Code-Segments
0x0008       8 B      code_end_va        uint64 LE  Virtuelle Endadresse des Code-Segments
0x0010       4 B      mode               uint32 LE  Integritätsmodus: 1=lockstep, 2=scrubbed, 3=hw_ecc
0x0014       4 B      interval_ms        uint32 LE  Sweep-Intervall in Millisekunden
0x0018       8 B      recovery_ptr       uint64 LE  Adresse des Recovery-Handlers (0 = nicht gesetzt)
0x0020       4 B      hash_copy_1        uint32 LE  CRC32 (IEEE 802.3) des Code-Segments — Kopie 1
0x0024    4092 B      padding_1          —          Null-Bytes (Seitentrennung)
0x1020       4 B      hash_copy_2        uint32 LE  CRC32 — Kopie 2
0x1024    4092 B      padding_2          —          Null-Bytes
0x2020       4 B      hash_copy_3        uint32 LE  CRC32 — Kopie 3
0x2024       4 B      padding_end        —          Abschluss-Padding (gesamt: 8232 Byte)


2. Modus-Werte

Wert (uint32 LE) Modus Bedeutung
1 software_lockstep Instruktions-Redundanz für ALU/FPU — kein periodischer Sweep
2 scrubbed Periodischer CRC32-Sweep des Code-Segments
3 hardware_ecc Vertrauen auf Hardware-ECC — kein Software-Sweep

Bei software_lockstep wird .meta_safe trotzdem erzeugt (Hashes als Referenz), der Sweep-Mechanismus ist aber deaktiviert.


3. Compiler-Workflow (Post-Patching)

Die CRC32-Hashes können erst nach der vollständigen Code-Generierung berechnet werden — ein Henne-Ei-Problem. Lyx löst es durch einen zweistufigen Build:

1. Code-Generierung
     ┌─────────────────────────────────────────┐
     │  Backend erzeugt Maschinencode           │
     │  .meta_safe wird mit Platzhaltern (0x00) │
     │  angelegt und ins ELF eingebettet        │
     └────────────────────┬────────────────────┘
                          │
  2. CRC32-Berechnung
     ┌─────────────────────────────────────────┐
     │  Compiler liest fertiges Code-Segment    │
     │  Berechnet CRC32 (IEEE 802.3) über       │
     │  [code_start_va … code_end_va]           │
     └────────────────────┬────────────────────┘
                          │
  3. Post-Patching
     ┌─────────────────────────────────────────┐
     │  Compiler überschreibt in der ELF-Datei: │
     │    Offset 0x20: hash_copy_1 = CRC32      │
     │    Offset 0x1020: hash_copy_2 = CRC32    │
     │    Offset 0x2020: hash_copy_3 = CRC32    │
     └─────────────────────────────────────────┘

Das fertige ELF enthält drei identische, korrekte Hashes in .meta_safe.


4. Sektion im Linker-Script

Für Bare-Metal-Targets muss das Linker-Script .meta_safe explizit platzieren. Die drei Hash-Kopien sollten auf physisch verschiedene Speicherbereiche verteilt sein — bei SRAM-Targets auf verschiedene Speichermodule oder -bänke, sofern vorhanden:

/* Linker-Script-Ausschnitt (ARM Cortex-M, STM32F4) */

/* Flash-Layout */
MEMORY {
    FLASH   (rx)  : ORIGIN = 0x08000000, LENGTH = 1024K
    SRAM    (rwx) : ORIGIN = 0x20000000, LENGTH = 192K
    SRAM2   (rwx) : ORIGIN = 0x2001C000, LENGTH = 16K
    BACKUP  (rw)  : ORIGIN = 0x40024000, LENGTH = 4K
}

SECTIONS {
    /* Normaler Code im Flash */
    .text : {
        *(.isr_vector)
        *(.text*)
        *(.rodata*)
    } > FLASH

    /* .meta_safe nach dem normalen Code */
    .meta_safe : {
        KEEP(*(.meta_safe))
    } > FLASH

    /* TMR-Datenkopien auf physisch verschiedene Speicher */
    .tmr_a : { *(.tmr_a) } > SRAM
    .tmr_b : { *(.tmr_b) } > SRAM2
    .tmr_c : { *(.tmr_c) } > BACKUP
}

Wichtig: .meta_safe selbst muss im Flash (nicht im RAM) liegen — Flash-Speicher ist resistenter gegen SEUs als SRAM und wird typischerweise von der Hardware-ECC des MCUs geschützt. Ein Bit-Flip in den Referenzhashes im Flash ist unwahrscheinlicher als im SRAM.

5. Manuell verifizieren

Der CRC32 in .meta_safe lässt sich nach dem Build unabhängig verifizieren — ein wichtiger Schritt in der DO-178C-Qualifikationskette:

// Variante 1: Lyx-eigenes Tool
// lyxc --verify-integrity flight_control.elf
//
// Ausgabe:
//   .meta_safe found at offset 0x12400 (8232 bytes)
//   code_start_va:  0x08000200
//   code_end_va:    0x08012340
//   mode:           scrubbed (2), interval: 100 ms
//   hash_copy_1:    0xA3F2E811 ✓
//   hash_copy_2:    0xA3F2E811 ✓
//   hash_copy_3:    0xA3F2E811 ✓
//   Recomputed CRC: 0xA3F2E811 ✓
//   INTEGRITY VERIFIED

// Variante 2: Unabhängige Verifikation mit Standard-Tools
// readelf -S flight_control.elf | grep meta_safe
// → zeigt Offset und Größe
//
// objcopy --dump-section .meta_safe=meta.bin flight_control.elf
// → exportiert die Sektion als Binärdatei
//
// hexdump -C meta.bin | head
// → Offsets 0x20, 0x1020, 0x2020 zeigen die drei Hashes


6. Zugriff aus der Anwendung

Neben dem automatischen Hintergrund-Sweep kann die Anwendung explizit abfragen:

@integrity(mode: scrubbed, interval: 100)
unit flight_kernel;

fn StartupSelfTest(): bool {
    // Liest .meta_safe, berechnet Ist-CRC, führt TMR-Vergleich durch
    return VerifyIntegrity();
}

fn main(): int64 {
    if (StartupSelfTest() = false) {
        // Korrumpierter Code — sicheren Zustand einleiten
        ActivateBackupSystem();
        while (true) { }   // Hier bleiben bis Reset
    }

    // Normaler Betrieb
    RunMainLoop();
    return 0;
}


7. Einschränkungen

Einschränkung Begründung
.meta_safe ist kein vollständiger Authentizitätsnachweis CRC32 ist kein kryptographischer Hash — ein Angreifer kann CRC32 gezielt manipulieren. Das ist kein Angriffsvektor für Avionik (physisch gesichert), aber relevant für andere Kontexte.
Sweep erkennt keinen Fehler in .meta_safe selbst Wenn alle drei Hashes korrumpiert sind (unwahrscheinlich im Flash), liefert der TMR-Vergleich eine falsch positive Aussage. ECC-RAM für Flash ist die Gegenmaßnahme.
Code-Segment-Grenzen müssen korrekt im Linker-Script definiert sein Fehlerhafte code_start_va/code_end_va führen zu falschen CRC32-Berechnungen. Immer mit –verify-integrity nach dem Build prüfen.

Letzte Aktualisierung: 2026-05-22