ELF64, linkedição e a imagem do kernel ChrisOS¶
Sobre este capítulo Layout do executável e entrada
Neste capítulo
- ELF64, linkedição e a imagem do kernel ChrisOS
- Escopo
- Visão de link e visão de carregamento
- Tipos de arquivo ELF
- Por que objetos relocáveis existem
- Identificação ELF
- ELF64 header
- Entry point
- Program headers
- PT_LOAD
- Imagem no arquivo versus imagem em memória
- BSS
- p_filesz versus p_memsz
- Permissões de segmentos
- Segmento de requests Limine
- Text e rodata
- Data
- Alinhamento
- p_paddr
- Sections
- Section versus segment
- Section headers e boot
- Symbols
- Symbols locais e globais
- Undefined symbols
- Endereço final de um symbol
- Relocations
- REL e RELA
- R_X86_64_64
- R_X86_64_PC32
- R_X86_64_PLT32
- R_X86_64_32
- Limitação atual de R_X86_64_32S
- Overflow de relocation
- Kernel code model
- Kernel fixo, não PIE
- Static e nostdlib
- Linker script como política
- Symbols criados pelo linker
- __kernel_start e __kernel_end
- __stack_bottom e __stack_top
- COMMON
- Sections descartadas
- Ordem das sections
- Ordem dos objetos e reprodutibilidade
- GOT e PLT
- Estruturas ELF dinâmicas
- Comando de link de produção
- Post-link stamping
- ChrisO v2 atual
- ChrisO não é ELF ET_REL
- Link de múltiplos objetos no ChrisLd
- Layout atual do ChrisLd
- BSS no ChrisLd
- Resolução de symbols
- Entry por comparação exata
- Validador atual do ChrisLd
- Source atual versus audits antigos
- O que falta ao ChrisLd para kernel.elf
- Limite de objetos
- Limite de output
- Capacidades fixas do ChrisO
- Diferenças de alinhamento
- Simplificação de p_paddr
- ELF loader de user mode
- Janela de endereço de user mode
- BSS do user loader
- W^X do user loader
- Entry executável
- Overlap
- Bounds do arquivo
- Algoritmo de static linking
- Linking como grafo
- Layout antes da relocation final
- Garbage collection
- Determinismo
- Link map
- Gate diferencial
- Gate de equivalência para kernel
- Fronteira self-hosted atual
- Checker reproduzível
- Matriz atual
- Limite de validação
- Gatilhos de revisão
- Referências primárias
Escopo¶
O kernel do ChrisOS não é apenas uma sequência crua de instruções x86-64. Ele é um executável ELF64 cuja estrutura informa ao bootloader qual arquitetura deve executar a imagem, onde está o entry point, quais bytes precisam ser carregados, quais endereços virtuais devem receber esses bytes, quais regiões existem apenas em memória e quais permissões de leitura, escrita e execução cada região deve possuir.
Antes do ELF final existir, o toolchain trabalha com seções, símbolos, referências indefinidas, relocations, alinhamentos e endereços que ainda não foram definidos.
O pipeline de produção atual é:
fontes C / assembly
|
+-- GCC do host
+-- assembler
|
v
objetos relocáveis
|
v
ld do host
-static
-nostdlib
-T kernel/metal/linker.ld
|
v
kernel.elf
ELF64
ET_EXEC
EM_X86_64
higher-half
ENTRY(kstart)
segmento de requests Limine
|
v
Limine
|
v
imagem do kernel mapeada
O ChrisLd nativo está evoluindo em direção a esse alvo, mas ainda não gera uma imagem equivalente ao kernel de produção.
Visão de link e visão de carregamento¶
ELF possui duas visões relacionadas.
Durante a linkedição, os elementos centrais são sections, symbols e relocations.
Durante o carregamento, os elementos centrais são program headers, segments e o entry point.
A distinção essencial é:
sections
servem principalmente ao linker,
debugger e ferramentas de análise
program headers
servem principalmente ao loader
O bootloader não precisa reconstruir cada seção fonte. Ele precisa criar a imagem de memória descrita pelos program headers.
Tipos de arquivo ELF¶
Tipos importantes são:
| Tipo | Significado |
|---|---|
| ET_REL | objeto relocável |
| ET_EXEC | executável |
| ET_DYN | shared object ou executável position-independent |
| ET_CORE | core dump |
O kernel final do ChrisOS é ET_EXEC.
Objetos intermediários produzidos pelo compilador são relocáveis porque vários endereços só podem ser conhecidos quando todo o conjunto de objetos for combinado.
Por que objetos relocáveis existem¶
Se uma unidade de compilação chama uma função definida em outro arquivo, o compiler consegue emitir a instrução de chamada, mas ainda não conhece o endereço final do destino.
O objeto registra:
- bytes de machine code;
- referência a um symbol;
- local da relocation;
- tipo da relocation;
- addend quando aplicável.
O linker determina o layout, resolve o símbolo e corrige os bytes.
Identificação ELF¶
Todo ELF começa com:
No ChrisOS:
Portanto as estruturas são ELF de 64 bits e os inteiros são little-endian.
ELF64 header¶
O header ELF64 possui 64 bytes.
Campos importantes:
| Campo | Finalidade |
|---|---|
| e_ident | identificação |
| e_type | tipo do objeto |
| e_machine | arquitetura |
| e_version | versão ELF |
| e_entry | endereço virtual de entrada |
| e_phoff | offset dos program headers |
| e_shoff | offset dos section headers |
| e_flags | flags de arquitetura |
| e_ehsize | tamanho do header |
| e_phentsize | tamanho de cada program header |
| e_phnum | quantidade de program headers |
| e_shentsize | tamanho de cada section header |
| e_shnum | quantidade de sections |
| e_shstrndx | índice da tabela de nomes |
Para x86-64:
62 corresponde a EM_X86_64.
Entry point¶
e_entry contém o endereço virtual da primeira instrução.
O linker script de produção declara:
O linker resolve o endereço final de kstart e o grava no ELF header.
O Limine entra nesse endereço porque o ChrisOS não utiliza um Entry Point request separado.
Program headers¶
Cada program header ELF64 contém:
- p_type;
- p_flags;
- p_offset;
- p_vaddr;
- p_paddr;
- p_filesz;
- p_memsz;
- p_align.
PT_LOAD é o tipo central para o kernel.
PT_LOAD¶
Um PT_LOAD determina:
copiar p_filesz bytes
do offset p_offset no arquivo
para o endereço virtual p_vaddr
reservando p_memsz bytes em memória
Se p_memsz for maior que p_filesz, a diferença deve ser zerada.
Imagem no arquivo versus imagem em memória¶
Para um segmento:
O loader copia o prefixo presente no arquivo e zera o restante.
O executável em disco pode assim ser muito menor que a imagem runtime.
BSS¶
Variáveis globais/static não inicializadas ou inicializadas com zero normalmente ficam em BSS.
O script atual contém:
.bss (NOLOAD) : ALIGN(4K) {
*(.bss .bss.*)
*(COMMON)
. = ALIGN(16);
__stack_bottom = .;
. += 1024K;
__stack_top = .;
. = ALIGN(4K);
__kernel_end = .;
} :data
Isso:
- coleta BSS;
- inclui COMMON;
- reserva 1 MiB para a região de stack;
- cria os symbols da stack;
- cria __kernel_end;
- aumenta o tamanho em memória do segmento RW sem gravar 1 MiB de zeros no ELF.
p_filesz versus p_memsz¶
Se um segmento tiver 12 KiB de data inicializado, 40 KiB de BSS e stack reservada de 1024 KiB:
Alinhamentos podem adicionar gaps.
A diferença é memória zerada criada pelo loader.
Permissões de segmentos¶
As flags ELF são:
O linker script define:
Nenhum PT_LOAD de produção é simultaneamente gravável e executável.
Segmento de requests Limine¶
Esse segmento contém:
Ele precisa ser RW porque o Limine escreve response pointers nas estruturas antes de entrar no kernel.
Não precisa ser executável.
As permissões ELF representam diretamente o contrato do protocolo de boot.
Text e rodata¶
.text e .rodata são atribuídas ao mesmo program header text.
Logo constantes read-only ficam hoje no mesmo segmento RX do código.
Elas não são graváveis, mas o mapping é executável.
Um layout futuro mais estrito poderia separar:
além do segmento de requests.
O desenho atual ainda evita W+X.
Data¶
.data e .bss pertencem ao segmento RW.
A stack reservada pelo linker também amplia esse segmento em memória.
Bytes inicializados existem no arquivo; BSS e stack são representados principalmente por p_memsz.
Alinhamento¶
O link host utiliza:
e as principais sections de saída são alinhadas a 4 KiB.
A relação necessária para PT_LOAD é:
Isso permite mappings orientados a páginas.
p_paddr¶
ELF também possui p_paddr.
No caminho do ChrisOS, o Limine controla o backing físico real enquanto respeita o layout virtual.
O p_vaddr higher-half não é o endereço físico do kernel em RAM.
Accounting físico não deve derivar o endereço físico do link address.
Sections¶
Sections comuns incluem:
O section header descreve propriedades como:
- nome;
- tipo;
- flags;
- endereço;
- offset;
- tamanho;
- alignment;
- relações com outras sections.
Section versus segment¶
Várias sections podem ocupar um único segmento.
No ChrisOS:
e:
O linker organiza sections. O loader mapeia segments.
Section headers e boot¶
O Limine usa principalmente os program headers para construir a imagem runtime.
Muitos section headers poderiam ser removidos sem impedir o carregamento, desde que program headers e entry continuem válidos.
Mesmo assim, sections permanecem úteis para:
- debug;
- disassembly;
- symbolization;
- inspeção;
- linking.
Symbols¶
Um symbol descreve uma entidade nomeada.
Atributos relevantes:
- name;
- value ou offset;
- size;
- binding;
- kind;
- section.
Bindings comuns incluem local, global e weak.
Kinds comuns incluem function, object, section e no-type.
Symbols locais e globais¶
Local não participa da resolução global entre objetos.
Global pode satisfazer referências externas.
Duas definições globais incompatíveis do mesmo nome normalmente devem gerar erro.
O ChrisLd atual rejeita duplicate globals.
Undefined symbols¶
Um undefined symbol representa uma dependência.
O objeto usa o nome, mas não o define.
Durante static linking, o linker precisa encontrar uma definição válida.
Se não existir, a linkedição precisa falhar.
Endereço final de um symbol¶
Após o layout:
O ChrisLd atual calcula essa relação para text, rodata, data e BSS.
Relocations¶
Relocation instrui o linker a calcular os bytes finais de uma referência.
A notação usual é:
Exemplos:
no modelo de binding estático usado pelo ChrisLd atual.
REL e RELA¶
REL mantém o addend implicitamente nos bytes do target.
RELA possui addend explícito no próprio record.
x86-64 usa amplamente relocations no estilo RELA.
ChrisoRel v2 possui addend assinado explícito.
R_X86_64_64¶
Grava um endereço absoluto de 64 bits.
É útil para ponteiros cujo endereço final só é conhecido no link.
R_X86_64_PC32¶
Grava deslocamento relativo de 32 bits:
O resultado precisa caber em int32:
O ChrisLd atual rejeita overflow.
R_X86_64_PLT32¶
Compilers frequentemente usam PLT32 em calls externas.
Em static linking, quando o destino é conhecido, o linker pode ligar a call diretamente.
O ChrisLd usa a mesma fórmula PC-relative.
R_X86_64_32¶
É uma relocation absoluta de 32 bits.
O ChrisLd rejeita valores acima de 0xffffffff.
Limitação atual de R_X86_64_32S¶
R_X86_64_32S possui semântica signed de 32 bits no ABI x86-64.
O ChrisLd atual aplica a mesma verificação superior usada por R_X86_64_32.
Portanto sua implementação de 32S ainda não reproduz completamente a regra signed do ABI.
Overflow de relocation¶
Truncar um PC-relative displacement inválido produziria branch para endereço incorreto.
O linker deve rejeitar relocation não representável ou usar outra estratégia de code generation.
Linking é uma transformação semântica, não concatenação de bytes.
Kernel code model¶
O GCC de produção usa:
Isso seleciona suposições de endereçamento apropriadas ao kernel x86-64 localizado na região canônica alta.
Compiler e linker precisam concordar sobre esse modelo.
Kernel fixo, não PIE¶
As flags também incluem:
e o linker fixa:
O kernel atual é ET_EXEC em endereço virtual fixo.
Ainda não é um kernel PIE/KASLR.
Static e nostdlib¶
O link usa:
O kernel não recebe automaticamente startup files, libc ou dynamic loader do host.
Todos os symbols necessários precisam vir dos objetos fornecidos explicitamente.
Linker script como política¶
ELF fornece mecanismos genéricos.
kernel/metal/linker.ld determina a política do ChrisOS:
- formato;
- arquitetura;
- entry;
- base virtual;
- segments;
- ordem das sections;
- alinhamento;
- metadata Limine;
- stack;
- symbols de fronteira;
- sections descartadas.
O próximo capítulo trata essa política isoladamente.
Symbols criados pelo linker¶
O script cria:
Eles não precisam ser definidos por um arquivo C.
O linker transforma fronteiras de layout em symbols consumíveis pelo kernel.
__kernel_start e __kernel_end¶
__kernel_start é atribuído antes das sections na base higher-half.
__kernel_end aparece depois de BSS, stack e alinhamento final.
Eles delimitam o espaço virtual linkado do kernel.
__stack_bottom e __stack_top¶
O linker alinha a 16 bytes, marca bottom, avança 1024 KiB, marca top e então alinha a página.
Isso reserva memória sem gravar um MiB de zeros no arquivo.
COMMON¶
O BSS inclui:
para acomodar tentative definitions que eventualmente apareçam como common symbols em objetos.
Sections descartadas¶
O script descarta:
O runtime atual não depende de unwind metadata do host, notes genéricas ou strings de comentário do compiler.
Se unwind avançado for implementado, essa política precisa ser revista.
Ordem das sections¶
O layout é:
0xffffffff80000000
|
+-- requests Limine
+-- text
+-- rodata
+-- data
+-- bss
+-- stack reservada
|
__kernel_end
A ordem influencia endereços, relocations e o hash do executável.
Ordem dos objetos e reprodutibilidade¶
O makefile entrega os objetos ao ld em ordem determinística.
Como input sections são concatenadas conforme política e ordem de entrada, reordenar objetos pode alterar:
- endereços de funções;
- endereços de globals;
- displacements de relocations;
- padding;
- hash final do kernel.
Um binário diferente não é necessariamente inválido, mas ordem determinística ajuda análise e comparação.
GOT e PLT¶
Programas position-independent e dinâmicos frequentemente utilizam Global Offset Table e Procedure Linkage Table.
O kernel atual desativa PIE/PIC e não depende de dynamic loader de userspace.
Por isso não precisa de um resolver runtime de GOT/PLT como requisito de boot.
Um objeto ainda pode conter R_X86_64_PLT32 e o static linker resolvê-lo diretamente.
Estruturas ELF dinâmicas¶
Executáveis dinâmicos podem conter:
O kernel de produção não depende disso.
O modelo atual é:
Comando de link de produção¶
O link autoritativo equivale a:
ld
-m elf_x86_64
-nostdlib
-static
-z max-page-size=0x1000
-z noexecstack
-T kernel/metal/linker.ld
-o kernel.elf
<object list...>
Depois o makefile executa stamp_kernel.
O ChrisLd ainda não substitui esse pipeline.
Post-link stamping¶
O artefato final não é somente a saída bruta do ld.
Existe:
após a linkedição.
A futura reprodução self-hosted precisa considerar também a semântica desse estágio de proveniência.
ChrisO v2 atual¶
O source atual define ChrisO versão 2.
As classes de section são:
Symbols possuem:
- name;
- section;
- offset;
- size;
- binding;
- kind.
Relocations possuem:
- target section;
- offset;
- symbol index;
- signed addend;
- relocation type.
Isso é consideravelmente mais avançado que alguns audits antigos do repositório.
ChrisO não é ELF ET_REL¶
ChrisO é um object format próprio.
A arquitetura é válida:
O formato intermediário não precisa ser ELF desde que carregue toda informação necessária ao link final.
Link de múltiplos objetos no ChrisLd¶
chrisld_link_objects atual:
- aceita vários ChrisO;
- organiza section classes;
- resolve globals;
- rejeita duplicate globals;
- resolve undefined symbols;
- aplica relocations;
- emite ELF64;
- valida invariantes estruturais.
É uma evolução significativa sobre o linker antigo de um único text blob.
Layout atual do ChrisLd¶
O source atual pode emitir:
O segundo segmento aparece se data ou BSS existirem.
BSS no ChrisLd¶
No segmento writable:
Essa é a representação ELF correta de zero-fill.
Resolução de symbols¶
Para cada relocation o ChrisLd:
- obtém o symbol referenciado;
- diferencia binding local/global/undefined;
- busca definições globais;
- rejeita ambiguidade;
- calcula endereço final do symbol;
- calcula o place da relocation;
- aplica a fórmula;
- rejeita overflow ou tipo inválido.
Esse é o núcleo de um static linker real.
Entry por comparação exata¶
O ChrisLd atual procura exatamente:
depois:
e, se nenhum existir, usa load_addr.
Isso é mais correto que audits antigos que descreviam prefix matching.
Validador atual do ChrisLd¶
chrisld_validate verifica:
- magic ELF;
- ELFCLASS64;
- little endian;
- EM_X86_64;
- tamanho esperado de program header;
- phnum não zero;
- p_filesz <= p_memsz;
- nenhum PT_LOAD W+X;
- ausência de overlap entre loads;
- entry dentro de segmento executável.
Essas invariantes são úteis, mas ainda não provam equivalência ao linker script de produção.
Source atual versus audits antigos¶
Alguns documentos do repositório são explicitamente snapshots históricos.
Eles podem ficar atrás da implementação.
No commit revisado, o source já possui BSS, data, rodata, multiple objects e relocation types que certos textos antigos ainda listam como ausentes.
Neste corpus:
O que falta ao ChrisLd para kernel.elf¶
O linker nativo ainda não reproduz toda a política de produção.
Faltam pontos como:
- PT_LOAD separado para requests Limine;
- coleta das três classes .limine_requests;
- semântica equivalente a KEEP;
- stack de 1 MiB criada no link;
- __kernel_start;
- __kernel_end;
- __stack_bottom;
- __stack_top;
- ordem exata das output sections;
- discard policy;
- escala suficiente para todos os objetos;
- cobertura de todas as combinations de relocations geradas pelo kernel completo;
- prova de aceitação pelo Limine;
- boot real até markers do ChrisOS.
Portanto:
Limite de objetos¶
O ChrisLd usa:
O makefile do kernel possui muito mais que 32 objetos.
É um blocker de escala imediato.
Limite de output¶
O ChrisLd define:
O linker de produção não pode depender de um teto pequeno fixo.
O mecanismo de output precisa crescer conforme o tamanho real da imagem.
Capacidades fixas do ChrisO¶
Existem limites como:
São aceitáveis para bootstrap, mas precisam ser medidos contra o kernel completo.
Diferenças de alinhamento¶
ChrisLd usa alinhamento interno de 16 bytes para contribuições e page alignment nos segmentos.
O host linker alinha cada major output section a 4 KiB.
Os layouts não são idênticos.
Layouts diferentes podem ser executáveis válidos, mas symbols de fronteira e metadata Limine precisam manter equivalência semântica.
Simplificação de p_paddr¶
O helper atual do ChrisLd grava o mesmo valor em p_vaddr e p_paddr.
No kernel higher-half carregado pelo Limine, placement físico é controlado pelo loader.
A política de p_paddr precisa ser validada contra o protocolo real e não interpretada como endereço físico canônico alto.
ELF loader de user mode¶
kernel/metal/elf.c carrega executáveis de usuário, não kernel.elf.
Mesmo assim, ele é uma segunda implementação útil das regras de ELF.
Valida:
- ELF64;
- little endian;
- ET_EXEC;
- EM_X86_64;
- bounds da program-header table;
- máximo de program headers;
- PT_NULL/PT_LOAD;
- filesz <= memsz;
- ausência de W+X;
- congruência page offset/vaddr;
- janela virtual de usuário;
- ausência de overlap;
- entry em segmento executável.
Janela de endereço de user mode¶
O loader atual restringe:
Isso não tem relação com o higher half do kernel.
ELF é o mesmo formato, mas cada loader aplica política própria.
BSS do user loader¶
O loader aloca páginas e as zera antes de copiar os bytes do arquivo.
A parte não copiada continua zero.
Isso implementa naturalmente p_memsz maior que p_filesz.
W^X do user loader¶
PF_W vira MM_WRITE.
Se PF_X não estiver presente, o mapping recebe MM_NX.
O loader rejeita W+X.
Isso é coerente com ChrisLd e linker de produção.
Entry executável¶
O user loader verifica que e_entry fica dentro de PT_LOAD executável.
O ChrisLd validator também verifica.
Isso evita entrar em data ou memória não executável.
Overlap¶
PT_LOADs sobrepostos são rejeitados.
Overlaps poderiam criar ambiguidades de permission, file copy e zero-fill.
Rejeitar simplifica o modelo de segurança.
Bounds do arquivo¶
O parser evita confiar em:
sem verificar overflow.
A forma segura é:
Parsing de executável é uma trust boundary.
Algoritmo de static linking¶
Um linker estático minimamente completo realiza:
Parse¶
Lê sections, symbols, relocations e metadata.
Validation¶
Rejeita offsets, counts e records inválidos.
Grouping¶
Agrupa inputs em classes como:
Layout¶
Escolhe endereços virtuais alinhados.
Placement¶
Registra a posição de cada input section dentro da output class.
Global symbol table¶
Coleta globals e rejeita duplicatas.
Undefined resolution¶
Toda dependência obrigatória precisa encontrar definição.
Final symbol address¶
Relocation application¶
Corrige code/data com fórmula e range check.
File emission¶
Grava text, rodata e data.
Zero-fill representation¶
Representa BSS e reservas por p_memsz.
ELF emission¶
Escreve ELF header e program headers.
Validation¶
Valida entry, permissions, overlap, alignment e sizes.
O ChrisLd atual implementa um subset de bootstrap desse processo.
Linking como grafo¶
Objetos formam um dependency graph.
Exemplo:
Definitions são nodes e references são edges.
O executable final exige todos os edges necessários resolvidos.
Layout antes da relocation final¶
O endereço final depende de:
- output section;
- ordem de objetos;
- alinhamento;
- tamanhos anteriores;
- gaps;
- segment boundaries.
Por isso o layout precisa ser conhecido antes de aplicar relocations finais.
Concatenação ingênua de text não escala para um kernel.
Garbage collection¶
Linkers podem eliminar sections não referenciadas.
Requests Limine são observados externamente pelo bootloader e podem não aparecer no grafo normal de symbols.
Por isso o host linker usa KEEP.
Qualquer dead-section elimination futuro no ChrisLd precisa de mecanismo equivalente.
Determinismo¶
Com mesmos inputs e configuração, o layout deve ser determinístico.
Fontes de nondeterminism incluem:
- ordem instável de objetos;
- hash map iteration;
- padding não inicializado;
- timestamps implícitos;
- IDs aleatórios.
O ChrisOS grava proveniência de build deliberadamente, então builds diferentes podem produzir bytes diferentes por design.
Link map¶
Um ChrisLd de produção deveria emitir mapa com:
- sections;
- addresses;
- sizes;
- object placement;
- symbols;
- segment permissions.
Isso facilita crash analysis, size regression e comparação com host ld.
Gate diferencial¶
Um teste forte pode linkar o mesmo conjunto compatível com:
e:
e comparar propriedades semânticas:
- entry;
- higher-half;
- segments;
- permissions;
- p_filesz/p_memsz;
- required symbols;
- relocation targets;
- request discoverability.
Não é necessário que os bytes sejam idênticos se ambos os layouts forem corretos.
Gate de equivalência para kernel¶
Um milestone real de ChrisLd deveria exigir:
ELFCLASS64
ET_EXEC
EM_X86_64
ENTRY(kstart)
higher-half
segmento RW de requests Limine
text RX
data RW
BSS zero-fill
stack de 1 MiB
kernel boundary symbols
todas as references resolvidas
nenhum PT_LOAD W+X
imagem aceita pelo Limine
QEMU alcança markers do ChrisOS
Só então faz sentido dizer que ChrisLd linka o kernel.
Fronteira self-hosted atual¶
O repositório não prova SH4 ou SH5 atualmente.
O compiler nativo ainda não compila o kernel inteiro.
Assembly nativo ainda possui blockers.
ChrisLd ainda não produziu BIN/KERNEL.ELF de produção que tenha bootado.
O kernel autoritativo continua host-built e host-linked.
Checker reproduzível¶
scripts/check_elf_linking_examples.py valida:
- tamanhos ELF64 e EM_X86_64;
- flags de program header;
- zero-fill por filesz/memsz;
- congruência de alinhamento;
- fórmulas R_X86_64_64, PC32 e PLT32;
- overflow PC32;
- ENTRY(kstart);
- base higher-half;
- três classes PT_LOAD de produção;
- BSS NOLOAD e stack de 1 MiB;
- linker flags do host;
- modelo ChrisO v2 atual;
- multi-object e relocations no ChrisLd;
- gaps atuais para kernel de produção;
- W^X, overlap e bounds do user ELF loader.
O checker não chama host ld e não compila kernel.elf.
Matriz atual¶
| Capability | Link host de produção | ChrisLd atual |
|---|---|---|
| ELF64 ET_EXEC | sim | sim |
| EM_X86_64 | sim | sim |
| virtual address higher-half | sim | pode emitir |
| kstart exato | sim | sim |
| múltiplos objetos | sim | sim, limitado |
| global symbol resolution | sim | sim |
| duplicate-global rejection | sim | sim |
| undefined-symbol rejection | sim | sim |
| R_X86_64_64 | sim | sim |
| R_X86_64_PC32 | sim | sim |
| R_X86_64_PLT32 | sim | sim |
| R_X86_64_32 | sim | sim |
| R_X86_64_32S completo | sim | parcial |
| text | sim | sim |
| rodata | sim | sim |
| data | sim | sim |
| BSS zero-fill | sim | sim |
| RX/RW separados | sim | sim |
| segmento Limine dedicado | sim | não |
| linker-script policy | sim | não |
| stack 1 MiB | sim | não |
| boundary symbols | sim | não |
| KEEP Limine | sim | não |
| escala completa de objetos | sim | não |
| kernel bootável de produção | sim | não provado |
Limite de validação¶
Este capítulo foi conciliado com:
O caminho autoritativo permanece:
Quando audits históricos divergem do código atual, o source revisado é tratado como verdade da implementação.
Execute:
Gatilhos de revisão¶
Revisar quando:
- flags do linker mudarem;
- base virtual do kernel mudar;
- policy de program headers mudar;
- rodata ganhar segmento R separado;
- novos relocation types surgirem;
- ChrisO mudar de versão;
- limites do ChrisLd mudarem;
- ChrisLd implementar requests Limine;
- ChrisLd implementar policy equivalente ao linker script;
- reserva da stack mudar;
- toolchain nativo linkar BIN/KERNEL.ELF;
- um kernel produzido pelo ChrisLd bootar.
Referências primárias¶
- System V ABI, formato ELF genérico.
- AMD64 System V ABI, relocations x86-64.
- linker script e makefile do ChrisOS.
- Sources atuais de ChrisO, ChrisLd e ELF loader listados no front matter.