From d7cb08134102b7a2410c48d2a1802193f9031e00 Mon Sep 17 00:00:00 2001 From: Kimplul Date: Sun, 29 May 2022 16:23:41 +0300 Subject: continue documentation efforts --- include/apos/elf.h | 558 ++++++++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 491 insertions(+), 67 deletions(-) (limited to 'include/apos/elf.h') diff --git a/include/apos/elf.h b/include/apos/elf.h index e6936a3..ad5c4da 100644 --- a/include/apos/elf.h +++ b/include/apos/elf.h @@ -12,188 +12,612 @@ #include #include -#define EI_MAGIC 0x7f454c46 +/** @name Magic. */ +/** @{ */ -#define ELFCLASSNONE 0x0 -#define ELFCLASS32 0x1 -#define ELFCLASS64 0x2 +/** Magic ELF header bytes. */ +#define EI_MAGIC 0x7f454c46 -#define ELFDATANONE 0x0 -#define ELFDATA2LSB 0x1 -#define ELFDATA2MSB 0x2 +/** @} */ -#define ELFOSABI_NONE 0x0 -#define ELFOSABI_SYSV 0x0 -#define ELFOSABI_NETBSD 0x2 -#define ELFOSABI_LINUX 0x3 -#define ELFOSABI_HURD 0x4 +/** @name ELF classification. */ +/** @{ */ + +/** ELF class none, likely invalid binary. */ +#define ELFCLASSNONE 0x0 + +/** ELF class 32, 32bit binary. */ +#define ELFCLASS32 0x1 + +/** ELF class 64, 64bit binary. */ +#define ELFCLASS64 0x2 + +/** @} */ + +/** @name ELF data formats. */ +/** @{ */ + +/** ELF data none, likely invalid binary. */ +#define ELFDATANONE 0x0 + +/** ELF data little endian. */ +#define ELFDATA2LSB 0x1 + +/** ELF data big endian. */ +#define ELFDATA2MSB 0x2 + +/** @} */ + +/** + * @name ELF ABIs. + * Missing apos, of course, not sure which of these I should use instead. Some + * BSD? + */ +/** @{ */ + +/** ELF operating system ABI none. Likely standalone binary. */ +#define ELFOSABI_NONE 0x0 + +/** ELF UNIX SystemV ABI. */ +#define ELFOSABI_SYSV 0x0 + +/** ELF NetBSD ABI. */ +#define ELFOSABI_NETBSD 0x2 + +/** ELF Linux ABI. */ +#define ELFOSABI_LINUX 0x3 + +/** ELF GNU Hurd ABI. */ +#define ELFOSABI_HURD 0x4 + +/** ELF FreeBSD ABI. */ #define ELFOSABI_FREEBSD 0x9 + +/** ELF OpenBSD ABI. */ #define ELFOSABI_OPENBSD 0xc -#define ET_NONE 0x0 -#define ET_REL 0x1 -#define ET_EXEC 0x2 -#define ET_DYN 0x3 -#define ET_CORE 0x4 +/** @} */ + +/** @name ELF binary types. */ +/** @{ */ + +/** Binary type none. Likely invalid binary. */ +#define ET_NONE 0x0 + +/** Relocatable file. */ +#define ET_REL 0x1 + +/** Executable file. */ +#define ET_EXEC 0x2 + +/** Shared object file. */ +#define ET_DYN 0x3 -#define EM_RISCV 0xf3 +/** Core file. */ +#define ET_CORE 0x4 +/** @} */ + +/** + * @name Machine architecture. + * Currently only RISCV supported. + */ +/** @{ */ + +/** Riscv. */ +#define EM_RISCV 0xf3 + +/** @} */ + +/** ELF identification data. */ struct __packed elf_ident { + /** Magic. \see EI_MAGIC. */ uint32_t ei_magic; + + /** ELF class. \see ELFCLASSNONE, ELFCLASS32, ELFCLASS64. */ uint8_t ei_class; + + /** ELF data formats. \see ELFDATANONE, ELFDATA2LSB, ELFDATA2MSB. */ uint8_t ei_data; + + /** ELF version. \c 1 for current, \c 0 for undefined. */ uint8_t ei_version; + + /** ELF ABI. \see ELFOSABI_NONE, ELFOSABI_SYSV, ELFOSABI_NETBSD, + * ELFOSABI_LINUX, ELFOSABI_HURD, ELFOSABI_FREEBSD. */ uint8_t ei_osabi; + + /** ELF ABI version. Depends on \c ei_osabi. */ uint8_t ei_abiversion; + + /** Padding. */ uint8_t ei_pad[7]; }; +/** ELF32 header for ELF binaries of class \ref ELFCLASS32. */ struct __packed elf32_header { + /** Common identity header. */ struct elf_ident e_ident; + + /** ELF type. \see ET_NONE, ET_REL, ET_EXEC, ET_DYN, ET_CORE. */ uint16_t e_type; + + /** Machine architecture. \see EM_RISCV. */ uint16_t e_machine; + + /** ELF version. \c 1 for current, \c 0 for undefined. */ uint32_t e_version; + + /** Entrypoint virtual address. */ uint32_t e_entry; + + /** Start of program header table within binary image. */ uint32_t e_phoff; + + /** Start of section header table within binary image. */ uint32_t e_shoff; + + /** Architecture dependent flags. */ uint32_t e_flags; + + /** Size of this header. 52 bytes for ELF32. */ uint16_t e_ehsize; + + /** Size of one program header table entry. */ uint16_t e_phentsize; + + /** Number of program header table entries. */ uint16_t e_phnum; + + /** Size of one section header table entry. */ uint16_t e_shentsize; + + /** Number of section header table entries. */ uint16_t e_shnum; + + /** Index into section header table where section names are kept. */ uint16_t e_shstrndx; }; +/** ELF64 header for ELF binaries of class \ref ELFCLASS64. */ struct __packed elf64_header { + /** Common identity header. */ struct elf_ident e_ident; + + /** ELF type. \see ET_NONE, ET_REL, ET_EXEC, ET_DYN, ET_CORE. */ uint16_t e_type; + + /** Machine architecture. \see EM_RISCV. */ uint16_t e_machine; + + /** ELF version. \c 1 for current, \c 0 for undefined. */ uint32_t e_version; + + /** Entrypoint virtual address. */ uint64_t e_entry; + + /** Start of program header table within binary image. */ uint64_t e_phoff; + + /** Start of section header table within binary image. */ uint64_t e_shoff; + + /** Architecture dependent flags. */ uint32_t e_flags; + + /** Size of this header. 64 bytes for ELF64. */ uint16_t e_ehsize; + + /** Size of one program header table entry. */ uint16_t e_phentsize; + + /** Number of program header table entries. */ uint16_t e_phnum; + + /** Size of one section header table entry. */ uint16_t e_shentsize; + + /** Number of section header table entries. */ uint16_t e_shnum; + + /** Index into section header table where section names are kept. */ uint16_t e_shstrndx; }; -#define PT_NULL 0x0 -#define PT_LOAD 0x1 +/** @name Program header table entry types. */ +/** @{ */ + +/** Null header type. */ +#define PT_NULL 0x0 + +/** Load header type. */ +#define PT_LOAD 0x1 + +/** Dynamic header type. */ #define PT_DYNAMIC 0x2 -#define PT_INTERP 0x3 -#define PT_NOTE 0x4 -#define PT_SHLIB 0x5 -#define PT_PHDR 0x6 -#define PT_TLS 0x7 -#define PT_LOOS 0x60000000 -#define PT_HIOS 0x6fffffff -#define PT_LOPROC 0x70000000 -#define PT_HIPROC 0x7fffffff - -#define PF_X (1 << 0) -#define PF_W (1 << 1) -#define PF_R (1 << 2) +/** Interpreter header type. */ +#define PT_INTERP 0x3 + +/** Note header type. */ +#define PT_NOTE 0x4 + +/** Reserved, unsepcifier header type. */ +#define PT_SHLIB 0x5 + +/** Program header table header type. */ +#define PT_PHDR 0x6 + +/** Thread local storage header type. */ +#define PT_TLS 0x7 + +/** Operating system specific low fence. */ +#define PT_LOOS 0x60000000 + +/** Operating system specific high fence. */ +#define PT_HIOS 0x6fffffff + +/** Processor specific low fence. */ +#define PT_LOPROC 0x70000000 + +/** Processor specific high fence. */ +#define PT_HIPROC 0x7fffffff + +/** @} */ + +/** @name Program header entry access types. */ +/** @{ */ + +/** Executable. */ +#define PF_X (1 << 0) + +/** Writable. */ +#define PF_W (1 << 1) + +/** Readable. */ +#define PF_R (1 << 2) + +/** @} */ + +/** ELF32 program header table entry. \see ELFCLASS32. */ struct __packed program32_header { + /** Program header entry type. \see PT_NULL, PT_LOAD, PT_DYNAMIC, + * PT_INTERP, PT_NOTE, PT_SHLIB, PT_PHDR, PT_TLS, PT_LOOS, PT_HIOS, + * PT_LOPROC, PT_HIPROC. */ uint32_t p_type; + + /** Offset in the binary image where the associated segment lies. */ uint32_t p_offset; + + /** Virtual address to first byte in segment. */ uint32_t p_vaddr; + + /** Physical address to first byte in segment. Currently ignored. */ uint32_t p_paddr; + + /** Segment size as bytes in binary image. */ uint32_t p_filesz; + + /** Segment size as bytes in memory. */ uint32_t p_memsz; + + /** Access flags for segment. \see PF_X, PF_W, PF_R. */ uint32_t p_flags; + + /** Alignment of segment. */ uint32_t p_align; }; +/** ELF64 program header table entry. \see ELFCLASS64. */ struct __packed program64_header { + /** Program header entry type. \see PT_NULL, PT_LOAD, PT_DYNAMIC, + * PT_INTERP, PT_NOTE, PT_SHLIB, PT_PHDR, PT_TLS, PT_LOOS, PT_HIOS, + * PT_LOPROC, PT_HIPROC. */ uint32_t p_type; + + /** Access flags for segment. \see PF_X, PF_W, PF_R. */ uint32_t p_flags; + + /** Offset in the binary image where the associated segment lies. */ uint64_t p_offset; + + /** Virtual address to first byte in segment. */ uint64_t p_vaddr; + + /** Physical address to first byte in segment. Currently ignored. */ uint64_t p_paddr; + + /** Segment size as bytes in binary image. */ uint64_t p_filesz; + + /** Segment size as bytes in memory. */ uint64_t p_memsz; + + /** Alignment of segment. */ uint64_t p_align; }; -#define SHT_NULL 0x0 -#define SH_PROGBITS 0x1 -#define SHT_SYMTAB 0x2 -#define SHT_STRTAB 0x3 -#define SHT_RELA 0x4 -#define SHT_HASH 0x5 -#define SHT_DYNAMIC 0x6 -#define SHT_NOTE 0x7 -#define SHT_NOBITS 0x8 -#define SHT_REL 0x9 -#define SHT_SHLIB 0x0a -#define SHT_DYNSYM 0x0b -#define SHT_INIT_ARRAY 0x0e -#define SHT_FINI_ARRAY 0x0f -#define SHT_PREINIT_ARRAY 0x10 -#define SHT_GROUP 0x11 -#define SHT_SYMTAB_SHNDX 0x12 -#define SHT_NUM 0x13 - -#define SHF_WRITE 0x1 -#define SHF_ALLOC 0x2 -#define SHF_EXECINSTR 0x4 -#define SHF_MERGE 0x10 -#define SHF_STRINGS 0x20 -#define SHF_INFO_LINK 0x40 -#define SHF_LINK_ODER 0x80 +/** @name Section header types. */ +/** @{ */ + +/** Null type. */ +#define SHT_NULL 0x0 + +/** Section contains information defined by the program. */ +#define SHT_PROGBITS 0x1 + +/** Section contains symbol table. */ +#define SHT_SYMTAB 0x2 + +/** Section contains string table. */ +#define SHT_STRTAB 0x3 + +/** Section contains relocation table with explicit addends. */ +#define SHT_RELA 0x4 + +/** Section contains hashes. */ +#define SHT_HASH 0x5 + +/** Section contains dynamic linking information. */ +#define SHT_DYNAMIC 0x6 + +/** Section contains notes. */ +#define SHT_NOTE 0x7 + +/** Section occupies no space in binary image. */ +#define SHT_NOBITS 0x8 + +/** Section contains relocation table. */ +#define SHT_REL 0x9 + +/** Reserved, unspecified semantincs. */ +#define SHT_SHLIB 0x0a + +/** Sections hold symbol table. */ +#define SHT_DYNSYM 0x0b + +/** Section contains array of pointers to initialization functions. */ +#define SHT_INIT_ARRAY 0x0e + +/** Section contains array of pointers to finalization functions. */ +#define SHT_FINI_ARRAY 0x0f + +/** Section contains array of pointers to preinitialization functions. */ +#define SHT_PREINIT_ARRAY 0x10 + +/** Section group. */ +#define SHT_GROUP 0x11 + +/** Section contains extended symbol table index. */ +#define SHT_SYMTAB_SHNDX 0x12 + +/** Number of reserved SHT_* values. */ +#define SHT_NUM 0x13 + +/** @} */ + +/** @name Section header flags. */ +/** @{ */ + +/** Section should be writable during execution. */ +#define SHF_WRITE 0x1 + +/** Section occupies memory during execution. */ +#define SHF_ALLOC 0x2 + +/** Section contains executable machine instructions. */ +#define SHF_EXECINSTR 0x4 + +/** Section might be merged. */ +#define SHF_MERGE 0x10 + +/** Section contains null-terminated strings. */ +#define SHF_STRINGS 0x20 + +/** Section contains section header table index. */ +#define SHF_INFO_LINK 0x40 + +/** Preserve order after combining. */ +#define SHF_LINK_ORDER 0x80 + +/** Non-standard OS specific handling. */ #define SHF_OS_NONCONFORMING 0x100 -#define SHF_GROUP 0x200 -#define SHF_TLS 0x400 -#define SHF_MASKOS 0x0ff00000 -#define SHF_MASKPROC 0xf0000000 +/** Section is a member of group. */ +#define SHF_GROUP 0x200 + +/** Section hold thread local data. */ +#define SHF_TLS 0x400 + +/** Operating system mask. */ +#define SHF_MASKOS 0x0ff00000 + +/** Processor mask. */ +#define SHF_MASKPROC 0xf0000000 + +/** @} */ + +/** ELF32 section header table entry. \see ELFCLASS32. */ struct __packed section32_header { + /** Section header name. */ uint32_t sh_name; + + /** Section header type. \see SHT_NULL, SHT_PROGBITS, SHT_SYMTAB, + * SHT_STRTAB, SHT_RELA, SHT_HASH, SHT_DYNAMIC, SHT_NOTE, SHT_NOBITS, + * SHT_REL, SHT_SHLIB, SHT_DYNSYM, SHT_INIT_ARRAY, SHT_FINI_ARRAY, + * SHT_PREINIT_ARRAY, SHT_GROUP, SHT_SYMTAB_SHNDX, SHT_NUM. */ uint32_t sh_type; + + /** Section header flags. \see SHF_WRITE, SHF_ALLOC, SHF_EXECINSTR, + * SHF_MERGE, SHF_STRINGS, SHF_INFO_LINK, SHF_LINK_ORDER, + * SHF_OS_NONCONFORMING, SHF_GROUP, SHF_TLS, SHF_MASKOS, SHF_MASKPROC. + */ uint32_t sh_flags; + + /** Section virtual address. */ uint32_t sh_addr; + + /** Offset of section in binary image. */ uint32_t sh_offset; + + /** Size as bytes in binary image. */ uint32_t sh_size; + + /** Interpretation depends on section header type. */ uint32_t sh_link; + + /** Interpretation depends on section header type. */ uint32_t sh_info; + + /** Alignment of section address. */ uint32_t sh_addralign; + + /** If section holds an array, each entry is of this size. */ uint32_t sh_entsize; }; +/** ELF64 section header table entry. \see ELFCLASS64. */ struct __packed section64_header { + /** Section header name. */ uint32_t sh_name; + + /** Section header type. \see SHT_NULL, SHT_PROGBITS, SHT_SYMTAB, + * SHT_STRTAB, SHT_RELA, SHT_HASH, SHT_DYNAMIC, SHT_NOTE, SHT_NOBITS, + * SHT_REL, SHT_SHLIB, SHT_DYNSYM, SHT_INIT_ARRAY, SHT_FINI_ARRAY, + * SHT_PREINIT_ARRAY, SHT_GROUP, SHT_SYMTAB_SHNDX, SHT_NUM. */ uint32_t sh_type; + + /** Section header flags. \see SHF_WRITE, SHF_ALLOC, SHF_EXECINSTR, + * SHF_MERGE, SHF_STRINGS, SHF_INFO_LINK, SHF_LINK_ORDER, + * SHF_OS_NONCONFORMING, SHF_GROUP, SHF_TLS, SHF_MASKOS, SHF_MASKPROC. + */ uint64_t sh_flags; + + /** Section virtual address. */ uint64_t sh_addr; + + /** Offset of section in binary image. */ uint64_t sh_offset; + + /** Size as bytes in binary image. */ uint64_t sh_size; + + /** Interpretation depends on section header type. */ uint32_t sh_link; + + /** Interpretation depends on section header type. */ uint32_t sh_info; + + /** Alignment of section address. */ uint64_t sh_addralign; + + /** If section holds an array, each entry is of this size. */ uint64_t s_entsize; }; -#define elf_indent(e) ((struct elf_ident *)e) -#define elf64_header(e) ((struct elf64_header *)e) -#define elf32_header(e) ((struct elf32_header *)e) +/** + * Get ELF identity from pointer. + * + * @param e Pointer to ELF identity. + * @return \c e as ELF identity. + * \see elf_ident. + */ +#define elf_indent(e) ((struct elf_ident *)e) + +/** + * Get ELF64 header from pointer. + * + * @param e Pointer to ELF64 header. + * @return \c e as ELF64 header. + * \see elf64_header. + */ +#define elf64_header(e) ((struct elf64_header *)e) + +/** + * Get ELF32 header from pointer. + * + * @param e Pointer to ELF32 header. + * @return \c e as ELF32 header. + * \see elf32_header. + */ +#define elf32_header(e) ((struct elf32_header *)e) + +/** Get ELF64 program header from pointer. + * + * @param p Pointer to ELF64 program header. + * @return \c p as ELF64 program header. + * \see program64_header. + */ #define program64_header(p) ((struct program64_header *)p) + +/** + * Get ELF32 program header from pointer. + * + * @param p Pointer to ELF32 program header. + * @return \c p as ELF32 program header. + * \see program32_header. + */ #define program32_header(p) ((struct program32_header *)p) + +/** + * Get ELF64 section header from pointer. + * + * @param s Pointer to ELF64 section header. + * @return \c s as ELF64 section header. + * \see section64_header. + */ #define section64_header(s) ((struct section64_header *)s) + +/** + * Get ELF32 section header from pointer. + * + * @param s Pointer to ELF32 section header. + * @return \c s as ELF32 section header. + * \see section32_header. + */ #define section32_header(s) ((struct section32_header *)s) +/** + * Get either ELF32 or ELF64 header property, depending on the class. + * + * @param c ELF class. \see ELFCLASS32, ELFCLASS64. + * @param e ELF header. \see elf32_header, elf64_header. + * @param p Property to get. + * @return \c p + */ #define elf_header_prop(c, e, p) \ (c == ELFCLASS64 ? elf64_header(e)->p : elf32_header(e)->p) + +/** + * Get Either ELF32 or ELF64 program header property, depending on the class. + * + * @param c ELF class. \see ELFCLASS32, ELFCLASS64. + * @param e ELF program header. \see program32_header, program64_header. + * @param p Property to get. + * @return \c p. + */ #define program_header_prop(c, e, p) \ (c == ELFCLASS64 ? program64_header(e)->p : program32_header(e)->p) + +/** + * Get either ELF32 or ELF64 section header property, depending on the class. + * + * @param c ELF class. \see ELFCLASS32, ELFCLASS64. + * @param e ELF section header. \see section32_header, section64_header. + * @param p Property to get. + * @return \c p. + */ #define section_header_prop(c, e, p) \ (c == ELFCLASS64 ? section64_header(e)->p : section32_header(e)->p) -vm_t load_elf(struct tcb *t, vm_t binary, vm_t interp); +/** + * Build up ELF memory image from binary image. + * + * @param p Process space in which to build the memory image. + * @param binary Virtual address of binary. + * @param interp Virtual address of optional interpreter. + * @return Virtual address of entry point. + */ +vm_t load_elf(struct tcb *p, vm_t binary, vm_t interp); #endif /* APOS_ELF_H */ -- cgit v1.3