# elf_format.md — Blueprint do formato ELF x86-64 (Neuro Language)

> **Objetivo:** descrever como pegar no *blob* de código gerado pelo `codegen_x86_64`
> e embrulhar isso num binário ELF64 mínimo que o NFDOS (Linux minimal) consegue arrancar.

Versão v0.1 é **radicalmente simples**:

- 64-bit, little-endian.
- `ET_EXEC` (executável simples, não relocável).
- Uma só `PT_LOAD` para `.text` (código).
- Sem `.data`, `.bss`, `.rodata`, `.dynamic`, `.reloc`, `.symtab`, etc.
- Sem secções visíveis (podemos até omitir a tabela de secções).

---

## 1. Visão geral

A tarefa do módulo `elf_format`:

```text
input:
  - blob de código máquina x86-64 (gerado por codegen_x86_64)
  - offset da função de entrada (ex: offset do símbolo _start no blob)

output:
  - ficheiro ELF64 binário, pronto para:
      - ser executado em userland (via NFDOS/Linux),
      - ou ser usado como payload em contexto futuro (boot, PID1, etc.).
````

v0.1 assume:

* o programa é **auto-contido** (sem dependência de libc),
* o código gerado já contém:

  * uma função `_start` (ou equivalente) como entrypoint,
  * ou pelo menos um `__main__` que `_start` invoca.

---

## 2. Layout do ELF v0.1

Layout simplificado em bytes:

```text
+--------------------------+ offset 0x0000
| ELF Header (64 bytes)    |
+--------------------------+ offset 0x0040
| Program Header (56 bytes)|
+--------------------------+ offset 0x0078 (arredondado)
| .text (código)           |
|  (blob do codegen)       |
+--------------------------+ fim do ficheiro
```

Notas:

* `e_ehsize` = 64
* `e_phoff` = 64
* `e_phentsize` = 56
* `e_phnum` = 1
* `e_shoff` = 0 e `e_shnum` = 0 (sem tabela de secções — loader não precisa disso)

---

## 3. ELF Header (ELF64) — Campos relevantes

### 3.1. `e_ident[]`

Primeiros 16 bytes:

* `EI_MAG0..3`: `0x7F 'E' 'L' 'F'`
* `EI_CLASS`: `ELFCLASS64` (2)
* `EI_DATA`: `ELFDATA2LSB` (1) — little endian
* `EI_VERSION`: `EV_CURRENT` (1)
* `EI_OSABI`: 0 (System V) é suficiente para Linux
* `EI_ABIVERSION`: 0
* resto preenchido com 0

### 3.2. Cabeçalho principal

Campos chave:

* `e_type`      = `ET_EXEC` (2)
* `e_machine`   = `EM_X86_64` (62)
* `e_version`   = 1
* `e_entry`     = endereço virtual do entrypoint (`_start`)
* `e_phoff`     = offset da tabela de program headers (normalmente `0x40`)
* `e_shoff`     = 0 (sem secções)
* `e_flags`     = 0
* `e_ehsize`    = 64 (tamanho do ELF header)
* `e_phentsize` = 56 (tamanho de `Elf64_Phdr`)
* `e_phnum`     = 1 (apenas um PT_LOAD)
* `e_shentsize` = 0
* `e_shnum`     = 0
* `e_shstrndx`  = 0

---

## 4. Program Header (PT_LOAD único)

Só temos um segmento a ser carregado pelo kernel:

* tipo: `PT_LOAD`
* flags: `PF_R | PF_X` (leitura + execução).
  *Se um dia tivermos `.data`, poderemos ter outro segmento PF_R|PF_W.*

### 4.1. Campos principais do `Elf64_Phdr`

Vamos fixar uma **base virtual** típica:

* `base_vaddr` = `0x00400000` (como executáveis normais em Linux)

Se `.text` começa no offset `text_off` (ex: 0x80), então:

* `p_type`   = `PT_LOAD` (1)
* `p_offset` = `text_off`
* `p_vaddr`  = `base_vaddr + text_off`
* `p_paddr`  = igual a `p_vaddr` (ignorável em user space)
* `p_filesz` = tamanho do blob `.text`
* `p_memsz`  = tamanho do blob `.text` (sem bss no v0.1)
* `p_flags`  = `PF_R | PF_X`
* `p_align`  = `0x1000` (alinhamento de página)

### 4.2. Entry point

O `e_entry` do ELF tem de apontar para o endereço virtual da instrução inicial:

```text
e_entry = base_vaddr + text_off + entry_offset
```

onde:

* `entry_offset` é o offset (dentro do blob `.text`) do label `_start` (ou `__main__` wrapper).
* `text_off` é o offset do início do `.text` no ficheiro (por ex. 0x80).

---

## 5. Interface entre `codegen_x86_64` e `elf_format`

Para manter os módulos bem separados:

### 5.1. `codegen_x86_64` exporta:

* `code_blob`: bytes de `.text`
* `entry_label`: nome lógico (ex: `_start` ou `__main__`)
* `entry_offset`: posição, em bytes, de `entry_label` dentro de `code_blob`

Em v0.1, podemos simplificar e dizer:

* o codegen **garante** que `_start` é o primeiro byte do blob:

  * então `entry_offset = 0`
  * e `e_entry = base_vaddr + text_off`

### 5.2. `elf_format` decide:

* `base_vaddr` (fixo em v0.1: 0x00400000)
* `text_off` (ex: 0x80)
* preenche o ELF header + program header,
* concatena o `code_blob` depois dos headers.

---

## 6. ELF mínimo, sem secções

v0.1 não precisa de:

* `.symtab`, `.strtab`
* `.text`, `.data` como secções formais
* `.debug_*`, DWARF
* `.dynamic`, `.interp`, `.rel.*`

Linux carrega executáveis `ET_EXEC` baseando-se **apenas**:

* na ELF header,
* na tabela de `Program Header`s (especialmente `PT_LOAD`, `PT_INTERP`, `PT_DYNAMIC` quando existem).

Como o binário é **estático e auto-contido**, basta o nosso único `PT_LOAD`.

---

## 7. Possíveis layouts concretos

### 7.1. Layout concreto v0.1 (proposto)

```text
Offset  Conteúdo
------  ---------------------------------------------------
0x0000  ELF Header (64 bytes)
0x0040  Program Header #0 (56 bytes)
0x0078  (padding opcional até alinhamento desejado)
0x0080  .text (code_blob do codegen_x86_64)
...     fim do ficheiro
```

Parâmetros típicos:

* `base_vaddr` = `0x00400000`
* `text_off`   = `0x80`
* `e_entry`    = `0x00400000 + 0x80` (se `_start` no início do blob)
* `p_offset`   = `0x80`
* `p_vaddr`    = `0x00400000 + 0x80`
* `p_filesz`   = `len(code_blob)`
* `p_memsz`    = `len(code_blob)`
* `p_flags`    = `PF_R | PF_X`
* `p_align`    = `0x1000`

---

## 8. Futuro: extensões além v0.1

Mais tarde, quando NeuroLang for além de `fib`:

### 8.1. Secções e debug

* Gerar `.text`, `.data`, `.bss` como secções reais.
* Tabela de secções (`e_shoff`, `e_shnum`, `e_shstrndx`).
* DWARF para debugging (opcional mas poderoso).

### 8.2. `ET_DYN` e PIE

* Compilar como `ET_DYN` (position-independent executables).
* Deixar o kernel escolher o endereço base.

### 8.3. Vários segmentos `PT_LOAD`

* Um para `.text` (R|X)
* Outro para `.data`/`.bss` (R|W)

### 8.4. Integração com runtime mais rico

* Se um dia usarmos libc ou um runtime C, podemos:

  * gerar objetos relocáveis (`.o`),
  * linkar com `ld` externo,
  * ou implementar um mini-linker interno.

---

## 9. Resumo

Para o v0.1 do NeuroLang:

* `elf_format` é um **embrulhador minimalista**:

  * escreve ELF64 header,
  * escreve 1 program header `PT_LOAD`,
  * escreve o blob `.text` do codegen,
  * define `e_entry` para apontar para `_start`.

* Sem secções, sem reloc, sem dinamismo.

* Perfeito para:

  * testar **NeuroLang → IR → x86-64 → ELF**,
  * correr exemplos como `fib(40)` nativamente sob NFDOS/Linux,
  * e construir confiança antes de complicar.

---

*Fim de `elf_format.md`*