Files
MentOS/mentos/inc/elf/elf.h
T
2021-10-05 14:29:24 +02:00

292 lines
9.9 KiB
C

/// MentOS, The Mentoring Operating system project
/// @file elf.h
/// @brief Function for multiboot support.
/// @copyright (c) 2014-2021 This file is distributed under the MIT License.
/// See LICENSE.md for details.
#pragma once
#include "process/process.h"
#include "stdint.h"
/// @defgroup header_segment_types Program Header Segment Types
/// @brief List of numeric defines which identify segment entries types.
/// @{
/// @brief Unused.
#define PT_NULL 0
/// @brief Specifies a loadable segment, described by p_filesz and p_memsz.
/// The bytes from the file are mapped to the beginning of the memory segment.
/// If the segment's memory size (p_memsz) is larger than the file
/// size (p_filesz), the extra bytes are defined to hold the value 0
/// and to follow the segment's initialized area. The file size can not
/// be larger than the memory size. Loadable segment entries in the program
/// header table appear in ascending order, sorted on the p_vaddr member.
#define PT_LOAD 1
/// @brief Specifies dynamic linking information.
#define PT_DYNAMIC 2
/// @brief Specifies the location and size of a null-terminated path name
/// to invoke as an interpreter. This segment type is mandatory for dynamic
/// executable files and can occur in shared objects. It cannot occur more
/// than once in a file. This type, if present, it must precede any loadable
/// segment entry.
#define PT_INTERP 3
/// @brief Specifies the location and size of auxiliary information.
#define PT_NOTE 4
/// @brief Reserved but has unspecified semantics.
#define PT_SHLIB 5
/// @brief Specifies the location and size of the program header table
/// itself, both in the file and in the memory image of the program.
/// This segment type cannot occur more than once in a file. Moreover,
/// it can occur only if the program header table is part of the memory
/// image of the program. This type, if present, must precede any loadable
/// segment entry.
#define PT_PHDR 6
/// @brief Section for supporting exception handling routines.
/// @details
/// The .eh_frame section has the same structure with .debug_frame,
/// which follows DWARF format. It represents the table that describes
/// how to set registers to restore the previous call frame at runtime.
#define PT_EH_FRAME 0x6474E550
/// @brief Is a program header which tells the system how to control
/// the stack when the ELF is loaded into memory.
#define PT_GNU_STACK 0x6474E551
/// @brief This segment indicates the memory region which should be made
/// Read-Only after relocation is done. This segment usually appears in a
/// dynamic link library and it contains .ctors, .dtors, .dynamic, .got s
/// ections. See paragraph below.
#define PT_GNU_RELRO 0x6474E552
/// @brief TODO: Document.
#define PT_LOPROC 0x70000000
/// @brief TODO: Document.
#define PT_HIPROC 0x7FFFFFFF
/// @}
/// Elf header ident size.
#define EI_NIDENT 16
/// @brief The elf starting section.
typedef struct elf_header {
/// Elf header identity bits.
uint8_t ident[EI_NIDENT];
/// Identifies object file type.
uint16_t type;
/// Specifies target instruction set architecture.
uint16_t machine;
/// Set to 1 for the original version of ELF.
uint32_t version;
/// This is the memory address of the entry point from where the process starts executing.
uint32_t entry;
/// Points to the start of the program header table.
uint32_t phoff;
/// TODO: Comment.
uint32_t shoff;
/// TODO: Comment.
uint32_t flags;
/// TODO: Comment.
uint16_t ehsize;
/// TODO: Comment.
uint16_t phentsize;
/// TODO: Comment.
uint16_t phnum;
/// TODO: Comment.
uint16_t shentsize;
/// TODO: Comment.
uint16_t shnum;
/// TODO: Comment.
uint16_t shstrndx;
} elf_header_t;
/// @brief The elf program header, holding program layout information
typedef struct elf_program_header {
/// Identifies the type of the segment.
uint32_t type;
/// Offset of the segment in the file image.
uint32_t offset;
/// Virtual address of the segment in memory.
uint32_t vaddr;
/// On systems where physical address is relevant, reserved for
/// segment's physical address.
uint32_t paddr;
/// Size in bytes of the segment in the file image. May be 0.
uint32_t filesz;
/// Size in bytes of the segment in memory. May be 0.
uint32_t memsz;
/// Segment-dependent flags.
uint32_t flags;
/// Values of 0 or 1 specify no alignment. Otherwise should be a positive,
/// integral power of 2, with p_vaddr equating p_offset modulus p_align.
uint32_t align;
} elf_program_header_t;
/// @brief A section header with all kinds of useful information
typedef struct elf_section_header {
/// TODO: Comment.
uint32_t name;
/// TODO: Comment.
uint32_t type;
/// TODO: Comment.
uint32_t flags;
/// TODO: Comment.
uint32_t addr;
/// TODO: Comment.
uint32_t offset;
/// TODO: Comment.
uint32_t size;
/// TODO: Comment.
uint32_t link;
/// TODO: Comment.
uint32_t info;
/// TODO: Comment.
uint32_t addralign;
/// TODO: Comment.
uint32_t entsize;
} elf_section_header_t;
/// @brief A symbol itself.
typedef struct elf_symbol {
/// TODO: Comment.
uint32_t name;
/// TODO: Comment.
uint32_t value;
/// TODO: Comment.
uint32_t size;
/// TODO: Comment.
uint8_t info;
/// TODO: Comment.
uint8_t other;
/// TODO: Comment.
uint16_t ndx;
} elf_symbol_t;
/// @brief Holds information about relocation object (that do not need an addend).
typedef struct elf_rel_t {
/// TODO: Comment.
uint32_t r_offset;
/// TODO: Comment.
uint32_t r_info;
} elf_rel_t;
/// @brief Holds information about relocation object (that need an addend).
typedef struct elf_rela_t {
/// TODO: Comment.
uint32_t r_offset;
/// TODO: Comment.
uint32_t r_info;
/// TODO: Comment.
int32_t r_addend;
} elf_rela_t;
/// @brief Fields index of ELF_IDENT.
enum Elf_Ident {
EI_MAG0 = 0, ///< 0x7F
EI_MAG1 = 1, ///< 'E'
EI_MAG2 = 2, ///< 'L'
EI_MAG3 = 3, ///< 'F'
EI_CLASS = 4, ///< Architecture (32/64)
EI_DATA = 5, ///< Set to either 1 or 2 to signify little or big endianness.
EI_VERSION = 6, ///< ELF Version
EI_OSABI = 7, ///< OS Specific
EI_ABIVERSION = 8, ///< OS Specific
EI_PAD = 9 ///< Padding
};
#define ELFMAG0 0x7F ///< e_ident[EI_MAG0]
#define ELFMAG1 'E' ///< e_ident[EI_MAG1]
#define ELFMAG2 'L' ///< e_ident[EI_MAG2]
#define ELFMAG3 'F' ///< e_ident[EI_MAG3]
#define ELFDATA2LSB 1 ///< Little Endian
#define ELFCLASS32 1 ///< 32-bit Architecture
/// @brief Type of ELF files.
typedef enum Elf_Type {
ET_NONE = 0, ///< Unkown Type
ET_REL = 1, ///< Relocatable File
ET_EXEC = 2 ///< Executable File
} Elf_Type;
#define EM_386 3 ///< x86 Machine Type.
#define EV_CURRENT 1 ///< ELF Current Version.
/// @brief Defines a number of different types of sections, which correspond
/// to values stored in the field sh_type in the section header
typedef enum ShT_Types {
SHT_NULL = 0, ///< Null section
SHT_PROGBITS = 1, ///< Program information
SHT_SYMTAB = 2, ///< Symbol table
SHT_STRTAB = 3, ///< String table
SHT_RELA = 4, ///< Relocation (w/ addend)
SHT_NOBITS = 8, ///< Not present in file
SHT_REL = 9, ///< Relocation (no addend)
} ShT_Types;
/// @brief ShT_Attributes corresponds to the field sh_flags, but are bit
/// flags rather than stand-alone values.
enum ShT_Attributes {
SHF_WRITE = 0x01, ///< Writable section
SHF_ALLOC = 0x02 ///< Exists in memory
};
/// @brief Provide access to teh symbol biding.
#define ELF32_ST_BIND(INFO) ((INFO) >> 4)
/// @brief Provide access to teh symbol type.
#define ELF32_ST_TYPE(INFO) ((INFO)&0x0F)
/// @brief Provides possible symbol bindings.
enum StT_Bindings {
STB_LOCAL = 0, ///< Local scope
STB_GLOBAL = 1, ///< Global scope
STB_WEAK = 2 ///< Weak, (ie. __attribute__((weak)))
};
/// @brief Provides a number of possible symbol types.
enum StT_Types {
STT_NOTYPE = 0, ///< No type
STT_OBJECT = 1, ///< Variables, arrays, etc.
STT_FUNC = 2 ///< Methods or functions
};
/// @brief Loads an ELF file into the memory of task.
/// @param task The task for which we load the ELF.
/// @param file The ELF file.
/// @param entry The ELF binary entry.
/// @return 0 if fails, 1 if succeed.
int elf_load_file(task_struct *task, vfs_file_t *file, uint32_t *entry);
/// @brief Checks if the file is a valid ELF.
/// @param file The file to check.
/// @param type The type of ELF file we expect.
/// @return 0 if fails, 1 if succeed.
int elf_check_file_type(vfs_file_t *file, Elf_Type type);
/// @brief Checks the correctness of the ELF header.
/// @param hdr The header to check.
/// @return 0 if fails, 1 if succeed.
int elf_check_file_header(elf_header_t *hdr);
/// @brief Checks the correctness of the ELF header magic number.
/// @param hdr The header to check.
/// @return 0 if fails, 1 if succeed.
int elf_check_magic_number(elf_header_t *hdr);
/// @brief Transforms the passed ELF type to string.
/// @param type The integer representing the ELF type.
/// @return The string representing the ELF type.
const char *elf_type_to_string(int type);
/// @brief Transforms the passed ELF section header type to string.
/// @param type The integer representing the ELF section header type.
/// @return The string representing the ELF section header type.
const char *elf_section_header_type_to_string(int type);
/// @brief Transforms the passed ELF symbol type to string.
/// @param type The integer representing the ELF symbol type.
/// @return The string representing the ELF symbol type.
const char *elf_symbol_type_to_string(int type);
/// @brief Transforms the passed ELF symbol bind to string.
/// @param bind The integer representing the ELF symbol bind.
/// @return The string representing the ELF symbol bind.
const char *elf_symbol_bind_to_string(int bind);