diff options
Diffstat (limited to 'docs')
| -rw-r--r-- | docs/arch.rst | 9 | ||||
| -rw-r--r-- | docs/briefs.rst | 9 | ||||
| -rw-r--r-- | docs/briefs/tb0001-pic-in-32-bit-x86-assembly.rst | 161 | ||||
| -rw-r--r-- | docs/briefs/tb0002-x86_64_bootstrap.rst | 154 | ||||
| -rw-r--r-- | docs/conf.py | 8 | ||||
| -rw-r--r-- | docs/cross.rst | 9 | ||||
| -rw-r--r-- | docs/index.rst | 3 | ||||
| -rw-r--r-- | docs/pre/arch/x86_64.rst (renamed from docs/arch/x86_64.rst) | 0 | ||||
| -rw-r--r-- | docs/pre/arch/x86_64/boot.rst (renamed from docs/arch/x86_64/boot.rst) | 0 | ||||
| -rw-r--r-- | docs/pre/arch/x86_64/boot/pointers.rst (renamed from docs/arch/x86_64/boot/pointers.rst) | 0 | ||||
| -rw-r--r-- | docs/pre/arch/x86_64/context_switching.rst (renamed from docs/arch/x86_64/context_switching.rst) | 0 | ||||
| -rw-r--r-- | docs/pre/arch/x86_64/context_switching/interrupt_descriptor_table.rst (renamed from docs/arch/x86_64/context_switching/interrupt_descriptor_table.rst) | 0 | ||||
| -rw-r--r-- | docs/pre/arch/x86_64/context_switching/interrupt_descriptor_table/gate_descriptor.rst (renamed from docs/arch/x86_64/context_switching/interrupt_descriptor_table/gate_descriptor.rst) | 0 | ||||
| -rw-r--r-- | docs/pre/arch/x86_64/context_switching/interrupt_descriptor_table/idt_flags.rst (renamed from docs/arch/x86_64/context_switching/interrupt_descriptor_table/idt_flags.rst) | 0 | ||||
| -rw-r--r-- | docs/pre/arch/x86_64/context_switching/interrupt_descriptor_table/interrupt_descriptor_table copy.rst (renamed from docs/arch/x86_64/context_switching/interrupt_descriptor_table/interrupt_descriptor_table copy.rst) | 0 | ||||
| -rw-r--r-- | docs/pre/arch/x86_64/context_switching/interrupt_descriptor_table/interrupt_descriptor_table_pointer copy.rst (renamed from docs/arch/x86_64/context_switching/interrupt_descriptor_table/interrupt_descriptor_table_pointer copy.rst) | 0 | ||||
| -rw-r--r-- | docs/pre/arch/x86_64/context_switching/interrupt_descriptor_table/ist_offset.rst (renamed from docs/arch/x86_64/context_switching/interrupt_descriptor_table/ist_offset.rst) | 0 | ||||
| -rw-r--r-- | docs/pre/arch/x86_64/context_switching/interrupt_descriptor_table/segment_selector.rst (renamed from docs/arch/x86_64/context_switching/interrupt_descriptor_table/segment_selector.rst) | 0 | ||||
| -rw-r--r-- | docs/pre/arch/x86_64/context_switching/main.rst (renamed from docs/arch/x86_64/context_switching/main.rst) | 0 | ||||
| -rw-r--r-- | docs/pre/arch/x86_64/context_switching/segment_descriptor_table.rst (renamed from docs/arch/x86_64/context_switching/segment_descriptor_table.rst) | 0 | ||||
| -rw-r--r-- | docs/pre/arch/x86_64/context_switching/segment_descriptor_table/access_byte.rst (renamed from docs/arch/x86_64/context_switching/segment_descriptor_table/access_byte.rst) | 0 | ||||
| -rw-r--r-- | docs/pre/arch/x86_64/context_switching/segment_descriptor_table/gdt_flags.rst (renamed from docs/arch/x86_64/context_switching/segment_descriptor_table/gdt_flags.rst) | 0 | ||||
| -rw-r--r-- | docs/pre/arch/x86_64/context_switching/segment_descriptor_table/global_descriptor_table.rst (renamed from docs/arch/x86_64/context_switching/segment_descriptor_table/global_descriptor_table.rst) | 0 | ||||
| -rw-r--r-- | docs/pre/arch/x86_64/context_switching/segment_descriptor_table/global_descriptor_table_pointer.rst (renamed from docs/arch/x86_64/context_switching/segment_descriptor_table/global_descriptor_table_pointer.rst) | 0 | ||||
| -rw-r--r-- | docs/pre/arch/x86_64/context_switching/segment_descriptor_table/segment_descriptor_base.rst (renamed from docs/arch/x86_64/context_switching/segment_descriptor_table/segment_descriptor_base.rst) | 0 | ||||
| -rw-r--r-- | docs/pre/arch/x86_64/context_switching/segment_descriptor_table/segment_descriptor_extension.rst (renamed from docs/arch/x86_64/context_switching/segment_descriptor_table/segment_descriptor_extension.rst) | 0 | ||||
| -rw-r--r-- | docs/pre/arch/x86_64/context_switching/segment_descriptor_table/segment_descriptor_type.rst (renamed from docs/arch/x86_64/context_switching/segment_descriptor_table/segment_descriptor_type.rst) | 0 | ||||
| -rw-r--r-- | docs/pre/arch/x86_64/context_switching/segment_descriptor_table/task_state_segment.rst (renamed from docs/arch/x86_64/context_switching/segment_descriptor_table/task_state_segment.rst) | 0 | ||||
| -rw-r--r-- | docs/pre/arch/x86_64/context_switching/syscall.rst (renamed from docs/arch/x86_64/context_switching/syscall.rst) | 0 | ||||
| -rw-r--r-- | docs/pre/arch/x86_64/context_switching/syscall/main.rst (renamed from docs/arch/x86_64/context_switching/syscall/main.rst) | 0 | ||||
| -rw-r--r-- | docs/pre/arch/x86_64/context_switching/syscall/syscall_enable.rst (renamed from docs/arch/x86_64/context_switching/syscall/syscall_enable.rst) | 0 | ||||
| -rw-r--r-- | docs/pre/arch/x86_64/context_switching/syscall/syscall_handler.rst (renamed from docs/arch/x86_64/context_switching/syscall/syscall_handler.rst) | 0 | ||||
| -rw-r--r-- | docs/pre/arch/x86_64/exception_handling.rst (renamed from docs/arch/x86_64/exception_handling.rst) | 0 | ||||
| -rw-r--r-- | docs/pre/arch/x86_64/exception_handling/assert.rst (renamed from docs/arch/x86_64/exception_handling/assert.rst) | 0 | ||||
| -rw-r--r-- | docs/pre/arch/x86_64/exception_handling/panic.rst (renamed from docs/arch/x86_64/exception_handling/panic.rst) | 0 | ||||
| -rw-r--r-- | docs/pre/arch/x86_64/interrupt_handling.rst (renamed from docs/arch/x86_64/interrupt_handling.rst) | 0 | ||||
| -rw-r--r-- | docs/pre/arch/x86_64/interrupt_handling/generic_interrupt_handler.rst (renamed from docs/arch/x86_64/interrupt_handling/generic_interrupt_handler.rst) | 0 | ||||
| -rw-r--r-- | docs/pre/arch/x86_64/io.rst (renamed from docs/arch/x86_64/io.rst) | 0 | ||||
| -rw-r--r-- | docs/pre/arch/x86_64/io/port_io.rst (renamed from docs/arch/x86_64/io/port_io.rst) | 0 | ||||
| -rw-r--r-- | docs/pre/arch/x86_64/kernel.rst (renamed from docs/arch/x86_64/kernel.rst) | 0 | ||||
| -rw-r--r-- | docs/pre/arch/x86_64/kernel/cpu.rst (renamed from docs/arch/x86_64/kernel/cpu.rst) | 0 | ||||
| -rw-r--r-- | docs/pre/arch/x86_64/kernel/cpu/call.rst (renamed from docs/arch/x86_64/kernel/cpu/call.rst) | 0 | ||||
| -rw-r--r-- | docs/pre/arch/x86_64/kernel/cpu/control_register.rst (renamed from docs/arch/x86_64/kernel/cpu/control_register.rst) | 0 | ||||
| -rw-r--r-- | docs/pre/arch/x86_64/kernel/cpu/gdtr.rst (renamed from docs/arch/x86_64/kernel/cpu/gdtr.rst) | 0 | ||||
| -rw-r--r-- | docs/pre/arch/x86_64/kernel/cpu/idtr.rst (renamed from docs/arch/x86_64/kernel/cpu/idtr.rst) | 0 | ||||
| -rw-r--r-- | docs/pre/arch/x86_64/kernel/cpu/if.rst (renamed from docs/arch/x86_64/kernel/cpu/if.rst) | 0 | ||||
| -rw-r--r-- | docs/pre/arch/x86_64/kernel/cpu/msr.rst (renamed from docs/arch/x86_64/kernel/cpu/msr.rst) | 0 | ||||
| -rw-r--r-- | docs/pre/arch/x86_64/kernel/cpu/segment_register.rst (renamed from docs/arch/x86_64/kernel/cpu/segment_register.rst) | 0 | ||||
| -rw-r--r-- | docs/pre/arch/x86_64/kernel/cpu/tlb.rst (renamed from docs/arch/x86_64/kernel/cpu/tlb.rst) | 0 | ||||
| -rw-r--r-- | docs/pre/arch/x86_64/kernel/cpu/tr.rst (renamed from docs/arch/x86_64/kernel/cpu/tr.rst) | 0 | ||||
| -rw-r--r-- | docs/pre/arch/x86_64/kernel/halt.rst (renamed from docs/arch/x86_64/kernel/halt.rst) | 0 | ||||
| -rw-r--r-- | docs/pre/arch/x86_64/kernel/main.rst (renamed from docs/arch/x86_64/kernel/main.rst) | 0 | ||||
| -rw-r--r-- | docs/pre/arch/x86_64/memory.rst (renamed from docs/arch/x86_64/memory.rst) | 0 | ||||
| -rw-r--r-- | docs/pre/arch/x86_64/memory/allocator.rst (renamed from docs/arch/x86_64/memory/allocator.rst) | 0 | ||||
| -rw-r--r-- | docs/pre/arch/x86_64/memory/allocator/area_frame_allocator.rst (renamed from docs/arch/x86_64/memory/allocator/area_frame_allocator.rst) | 0 | ||||
| -rw-r--r-- | docs/pre/arch/x86_64/memory/allocator/concept.rst (renamed from docs/arch/x86_64/memory/allocator/concept.rst) | 0 | ||||
| -rw-r--r-- | docs/pre/arch/x86_64/memory/allocator/physical_frame.rst (renamed from docs/arch/x86_64/memory/allocator/physical_frame.rst) | 0 | ||||
| -rw-r--r-- | docs/pre/arch/x86_64/memory/allocator/tiny_frame_allocator.rst (renamed from docs/arch/x86_64/memory/allocator/tiny_frame_allocator.rst) | 0 | ||||
| -rw-r--r-- | docs/pre/arch/x86_64/memory/cpu.rst (renamed from docs/arch/x86_64/memory/cpu.rst) | 0 | ||||
| -rw-r--r-- | docs/pre/arch/x86_64/memory/heap.rst (renamed from docs/arch/x86_64/memory/heap.rst) | 0 | ||||
| -rw-r--r-- | docs/pre/arch/x86_64/memory/heap/bump_allocator.rst (renamed from docs/arch/x86_64/memory/heap/bump_allocator.rst) | 0 | ||||
| -rw-r--r-- | docs/pre/arch/x86_64/memory/heap/global_heap_allocator.rst (renamed from docs/arch/x86_64/memory/heap/global_heap_allocator.rst) | 0 | ||||
| -rw-r--r-- | docs/pre/arch/x86_64/memory/heap/heap_allocator.rst (renamed from docs/arch/x86_64/memory/heap/heap_allocator.rst) | 0 | ||||
| -rw-r--r-- | docs/pre/arch/x86_64/memory/heap/linked_list_allocator.rst (renamed from docs/arch/x86_64/memory/heap/linked_list_allocator.rst) | 0 | ||||
| -rw-r--r-- | docs/pre/arch/x86_64/memory/heap/memory_block.rst (renamed from docs/arch/x86_64/memory/heap/memory_block.rst) | 0 | ||||
| -rw-r--r-- | docs/pre/arch/x86_64/memory/heap/user_heap_allocator.rst (renamed from docs/arch/x86_64/memory/heap/user_heap_allocator.rst) | 0 | ||||
| -rw-r--r-- | docs/pre/arch/x86_64/memory/main.rst (renamed from docs/arch/x86_64/memory/main.rst) | 0 | ||||
| -rw-r--r-- | docs/pre/arch/x86_64/memory/multiboot.rst (renamed from docs/arch/x86_64/memory/multiboot.rst) | 0 | ||||
| -rw-r--r-- | docs/pre/arch/x86_64/memory/multiboot/elf_symbols_section.rst (renamed from docs/arch/x86_64/memory/multiboot/elf_symbols_section.rst) | 0 | ||||
| -rw-r--r-- | docs/pre/arch/x86_64/memory/multiboot/info.rst (renamed from docs/arch/x86_64/memory/multiboot/info.rst) | 0 | ||||
| -rw-r--r-- | docs/pre/arch/x86_64/memory/multiboot/memory_map.rst (renamed from docs/arch/x86_64/memory/multiboot/memory_map.rst) | 0 | ||||
| -rw-r--r-- | docs/pre/arch/x86_64/memory/multiboot/reader.rst (renamed from docs/arch/x86_64/memory/multiboot/reader.rst) | 0 | ||||
| -rw-r--r-- | docs/pre/arch/x86_64/memory/paging.rst (renamed from docs/arch/x86_64/memory/paging.rst) | 0 | ||||
| -rw-r--r-- | docs/pre/arch/x86_64/memory/paging/active_page_table.rst (renamed from docs/arch/x86_64/memory/paging/active_page_table.rst) | 0 | ||||
| -rw-r--r-- | docs/pre/arch/x86_64/memory/paging/inactive_page_table.rst (renamed from docs/arch/x86_64/memory/paging/inactive_page_table.rst) | 0 | ||||
| -rw-r--r-- | docs/pre/arch/x86_64/memory/paging/kernel_mapper.rst (renamed from docs/arch/x86_64/memory/paging/kernel_mapper.rst) | 0 | ||||
| -rw-r--r-- | docs/pre/arch/x86_64/memory/paging/page_entry.rst (renamed from docs/arch/x86_64/memory/paging/page_entry.rst) | 0 | ||||
| -rw-r--r-- | docs/pre/arch/x86_64/memory/paging/page_table.rst (renamed from docs/arch/x86_64/memory/paging/page_table.rst) | 0 | ||||
| -rw-r--r-- | docs/pre/arch/x86_64/memory/paging/temporary_page.rst (renamed from docs/arch/x86_64/memory/paging/temporary_page.rst) | 0 | ||||
| -rw-r--r-- | docs/pre/arch/x86_64/memory/paging/virtual_page.rst (renamed from docs/arch/x86_64/memory/paging/virtual_page.rst) | 0 | ||||
| -rw-r--r-- | docs/pre/arch/x86_64/stl.rst (renamed from docs/arch/x86_64/stl.rst) | 0 | ||||
| -rw-r--r-- | docs/pre/arch/x86_64/stl/container.rst (renamed from docs/arch/x86_64/stl/container.rst) | 0 | ||||
| -rw-r--r-- | docs/pre/arch/x86_64/stl/contiguous_pointer_iterator.rst (renamed from docs/arch/x86_64/stl/contiguous_pointer_iterator.rst) | 0 | ||||
| -rw-r--r-- | docs/pre/arch/x86_64/stl/forward_value_iterator.rst (renamed from docs/arch/x86_64/stl/forward_value_iterator.rst) | 0 | ||||
| -rw-r--r-- | docs/pre/arch/x86_64/stl/mutex.rst (renamed from docs/arch/x86_64/stl/mutex.rst) | 0 | ||||
| -rw-r--r-- | docs/pre/arch/x86_64/stl/shared_pointer.rst (renamed from docs/arch/x86_64/stl/shared_pointer.rst) | 0 | ||||
| -rw-r--r-- | docs/pre/arch/x86_64/stl/stack.rst (renamed from docs/arch/x86_64/stl/stack.rst) | 0 | ||||
| -rw-r--r-- | docs/pre/arch/x86_64/stl/unique_pointer.rst (renamed from docs/arch/x86_64/stl/unique_pointer.rst) | 0 | ||||
| -rw-r--r-- | docs/pre/arch/x86_64/stl/vector.rst (renamed from docs/arch/x86_64/stl/vector.rst) | 0 | ||||
| -rw-r--r-- | docs/pre/arch/x86_64/user.rst (renamed from docs/arch/x86_64/user.rst) | 0 | ||||
| -rw-r--r-- | docs/pre/arch/x86_64/user/main.rst (renamed from docs/arch/x86_64/user/main.rst) | 0 | ||||
| -rw-r--r-- | docs/pre/arch/x86_64/video.rst (renamed from docs/arch/x86_64/video.rst) | 0 | ||||
| -rw-r--r-- | docs/pre/arch/x86_64/video/vga.rst (renamed from docs/arch/x86_64/video/vga.rst) | 0 | ||||
| -rw-r--r-- | docs/pre/arch/x86_64/video/vga/io.rst (renamed from docs/arch/x86_64/video/vga/io.rst) | 0 | ||||
| -rw-r--r-- | docs/pre/arch/x86_64/video/vga/text.rst (renamed from docs/arch/x86_64/video/vga/text.rst) | 0 | ||||
| -rw-r--r-- | docs/pre/cross/memory.rst (renamed from docs/cross/memory.rst) | 0 | ||||
| -rw-r--r-- | docs/pre/cross/memory/asm_pointer.rst (renamed from docs/cross/memory/asm_pointer.rst) | 0 | ||||
| -rw-r--r-- | docs/requirements.txt | 2 |
98 files changed, 331 insertions, 24 deletions
diff --git a/docs/arch.rst b/docs/arch.rst deleted file mode 100644 index 495d309..0000000 --- a/docs/arch.rst +++ /dev/null @@ -1,9 +0,0 @@ -Platform-Specific Infrastructure -================================ - -.. toctree:: - :maxdepth: 2 - :caption: Contents: - :glob: - - arch/* diff --git a/docs/briefs.rst b/docs/briefs.rst new file mode 100644 index 0000000..1931345 --- /dev/null +++ b/docs/briefs.rst @@ -0,0 +1,9 @@ +Technical Briefs +================ + +.. toctree:: + :maxdepth: 1 + :caption: Contents: + :glob: + + briefs/* diff --git a/docs/briefs/tb0001-pic-in-32-bit-x86-assembly.rst b/docs/briefs/tb0001-pic-in-32-bit-x86-assembly.rst new file mode 100644 index 0000000..503ff43 --- /dev/null +++ b/docs/briefs/tb0001-pic-in-32-bit-x86-assembly.rst @@ -0,0 +1,161 @@ +Technical Brief 0001: Position-Independent Code (PIC) in 32-bit x86 Assembly for PIE Kernels +============================================================================================ + +The design of a modern x86-64 kernel, compiled as a Position-Independent Executable (PIE), necessitates a 32-bit assembly bootstrap stage for initial hardware setup. +This architectural requirement, however, introduces significant challenges during the linking phase. +A linker error may manifest during this process, presenting the following diagnostic: + +.. code-block:: text + + relocation R_X86_64_32 against symbol `...' can not be used when making a PIE object; recompile with -fPIE + +This error arises despite the explicit use of the ``-fPIE`` compilation flag for the object file in question. +Its occurrence indicates a fundamental incompatibility between the linking model of a PIE and the machine code generated from conventional 32-bit assembly instructions that reference symbolic addresses. +This scenario reveals a critical distinction between compiler-generated position independence and the manual implementation required for hand-written assembly in a mixed-mode, relocatable binary. + +Root Cause Analysis +------------------- + +The cause of this issue is a conflict between the linking model mandated by a Position-Independent Executable and the addressing capabilities inherent to the 32-bit x86 instruction set architecture (ISA). + +- **Position-Independent Executable (PIE) Constraints:** + A PIE is a variant of the Executable and Linkable Format (ELF) [#1]_ designed to be loaded at an arbitrary virtual address and function correctly without modification. + A strict prerequisite for this functionality is the complete absence of absolute virtual addresses within the binary's code and data sections. + Consequently, all internal data and function references must be encoded relative to the instruction pointer. + In the x86-64 ISA, this is typically accomplished through the native ``IP``-relative addressing mode (e.g., ``mov symbol(%rip), %rax``), which generates relocations of type ``R_X86_64_PC32``. + These PC-relative relocations are resolved by the linker based on the distance between the instruction and the symbol, a value that is constant regardless of the final load address. + +- **32-bit Addressing Limitations:** + The 32-bit x86 ISA lacks a native mechanism for instruction-pointer-relative addressing. + When an assembly instruction references a symbol by its name (e.g., ``movl $symbol, %eax``), the assembler's default behavior is to generate a relocation entry of type ``R_X86_64_32``. + This entry serves as a directive for the linker to substitute the symbol's final, 32-bit absolute virtual address into the machine code during the linking phase. + This process fundamentally embeds a hardcoded address into the instruction, making the code position-dependent. + +- **Mismatch:** + During the final link stage, the linker encounters these requests for absolute addresses within the 32-bit object code. + However, the linker's output target is a PIE, a format that explicitly forbids such absolute relocations because they would violate its defining characteristic of being relocatable. + The ``-fPIE`` flag, being a directive for a *compiler*, influences the code generation strategy for high-level languages like C++ but has no semantic effect on hand-written assembly that utilizes instructions which inherently produce absolute address relocations. + The linker, therefore, correctly identifies this violation of the PIE contract and terminates with an error. + +Solution: Runtime Address Calculation +------------------------------------- + +Resolution of this conflict necessitates the manual implementation of position-independent code within the 32-bit assembly module. +The core principle of this technique is the elimination of all instructions that would otherwise generate absolute address relocations. +Instead, the absolute address of any required symbol must be calculated at runtime relative to the current instruction pointer. + +- **The ``call``/``pop`` Idiom:** + The canonical technique for obtaining the value of the 32-bit instruction pointer (``EIP``) involves a ``call`` to the immediately subsequent instruction. + The ``call`` instruction pushes its return address—which is the address of the next instruction—onto the stack. + A ``pop`` instruction can then retrieve this value into a general-purpose register. + + .. code-block:: gas + + call .Lget_eip + .Lget_eip: + popl %ebx + + Upon completion of this sequence, the ``%ebx`` register contains the absolute virtual address of the ``.Lget_eip`` label at runtime. + This address serves as a reliable anchor from which other symbols' addresses can be calculated. + +- **Establishing a Base Register:** + By convention, specifically within the i386 System V ABI, the ``%ebx`` register is designated for this purpose. + It is classified as a "callee-saved" register, which obligates any conforming function to preserve its value across calls. + By establishing ``%ebx`` as a base register at the commencement of the bootstrap sequence, its value can be reliably utilized for all subsequent address calculations within tha |
