#ifndef FORMAT_H #define FORMAT_H #include #include #include typedef uint32_t symbol; /// Begin a new ELF executable. void elf_executable(void); /// All definitions are complete. Finish processing the executable. void finish_executable(symbol entry_point); /// Create a new symbol. You will later have to define this with /// `define_executable_symbol`, `define_readonly_symbol`, /// or import it from an external library. symbol new_symbol(void); void define_executable_symbol(symbol sym); void define_readonly_symbol(symbol sym); void append_data(size_t size, const void* buf); void append_u8(uint8_t x); void append_u32(uint32_t x); void append_u64(uint64_t x); /// Assuming the symbol is located in the same segment as this code, /// insert a 32-bit offset for the symbol relative to the virtual address /// of the current address (Program Counter (PC)). /// /// This is used for generating relative jumps. /// /// If the symbol is defined in this object, then it will be computed /// at compile-time and not emitted as an actual relocation in the executable. void relocate_pc32(symbol sym); /// Like pc32 for DIY relocations. This returns INT32_MAX if the symbol /// has not been defined yet. This exists so that the assembler can manually /// emit 8-bit short jumps when the distance is short enough. /// /// The offset exists to account for the offset being relative to the /// *end* of an instruction, whereas the symbol offset is computed /// relative to `here`. This makes bounds-checking slightly easier. int32_t symbol_offset(symbol sym, int8_t offset); /// If the symbol is not in the same segment as this code, /// for example when linking against a dynamic library or accessing read-only data, /// then a 32-bit offset may not be sufficient to access a symbol with pc32. /// This necessitates a Global Offset Table (GOT) which contains the 64-bit /// absolute addresses of the symbols which *is* located in this segment. /// Thus, this relocation inserts a 32-bit PC-relative address which points /// into the location in the GOT which contains the 64-bit absolute address /// of the symbol. /// /// This is used for generating jumps to dynamic library code /// and for accessing data in a different segment (e.g. read-only symbols). void relocate_gotpcrel(symbol sym); /// Insert the 32-bit truncated size of a symbol. void relocate_size32(symbol sym); /// Insert the 64-bit size of a symbol. void relocate_size64(symbol sym); #endif