292 lines
10 KiB
C
292 lines
10 KiB
C
/// @file elf.h
|
|
/// @brief Function for managing the Executable and Linkable Format (ELF).
|
|
/// @copyright (c) 2014-2022 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;
|
|
/// Points to the start of the section header table.
|
|
uint32_t shoff;
|
|
/// Processor-specific flags.
|
|
uint32_t flags;
|
|
/// Size of ELF header, in bytes.
|
|
uint16_t ehsize;
|
|
/// Size of an entry in the program header table.
|
|
uint16_t phentsize;
|
|
/// Number of entries in the program header table.
|
|
uint16_t phnum;
|
|
/// Size of an entry in the section header table.
|
|
uint16_t shentsize;
|
|
/// Number of entries in the section header table.
|
|
uint16_t shnum;
|
|
/// Section header table index of sect name string table.
|
|
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);
|