diff options
author | Ian Moffett <ian@osmora.org> | 2024-03-07 17:28:00 -0500 |
---|---|---|
committer | Ian Moffett <ian@osmora.org> | 2024-03-07 17:28:32 -0500 |
commit | bd5969fc876a10b18613302db7087ef3c40f18e1 (patch) | |
tree | 7c2b8619afe902abf99570df2873fbdf40a4d1a1 /lib/mlibc/options/elf | |
parent | a95b38b1b92b172e6cc4e8e56a88a30cc65907b0 (diff) |
lib: Add mlibc
Signed-off-by: Ian Moffett <ian@osmora.org>
Diffstat (limited to 'lib/mlibc/options/elf')
-rw-r--r-- | lib/mlibc/options/elf/generic/phdr.cpp | 10 | ||||
-rw-r--r-- | lib/mlibc/options/elf/generic/startup.cpp | 73 | ||||
-rw-r--r-- | lib/mlibc/options/elf/include/elf.h | 667 | ||||
-rw-r--r-- | lib/mlibc/options/elf/include/link.h | 58 | ||||
-rw-r--r-- | lib/mlibc/options/elf/include/mlibc/elf/startup.h | 28 | ||||
-rw-r--r-- | lib/mlibc/options/elf/meson.build | 11 |
6 files changed, 847 insertions, 0 deletions
diff --git a/lib/mlibc/options/elf/generic/phdr.cpp b/lib/mlibc/options/elf/generic/phdr.cpp new file mode 100644 index 0000000..334d52c --- /dev/null +++ b/lib/mlibc/options/elf/generic/phdr.cpp @@ -0,0 +1,10 @@ +#include <link.h> + +#include <bits/ensure.h> +#include <mlibc/debug.hpp> + +extern "C" int __dlapi_iterate_phdr(int (*)(struct dl_phdr_info*, size_t, void*), void *); + +int dl_iterate_phdr(int (*callback)(struct dl_phdr_info*, size_t, void*), void *data) { + return __dlapi_iterate_phdr(callback, data); +} diff --git a/lib/mlibc/options/elf/generic/startup.cpp b/lib/mlibc/options/elf/generic/startup.cpp new file mode 100644 index 0000000..d53881b --- /dev/null +++ b/lib/mlibc/options/elf/generic/startup.cpp @@ -0,0 +1,73 @@ + +#include <errno.h> +#include <string.h> +#include <stdint.h> +#include <stdlib.h> +#include <bits/ensure.h> +#include <mlibc/elf/startup.h> +#include <mlibc/environment.hpp> + +extern "C" size_t __init_array_start[]; +extern "C" size_t __init_array_end[]; +extern "C" size_t __preinit_array_start[]; +extern "C" size_t __preinit_array_end[]; + +static int constructors_ran_already = 0; + +struct global_constructor_guard { + global_constructor_guard() { + constructors_ran_already = 1; + } +}; + +static global_constructor_guard g; + +void __mlibc_run_constructors() { +/* + if (!constructors_ran_already) { + size_t constructor_count = (size_t)__init_array_end - (size_t)__init_array_start; + constructor_count /= sizeof(void*); + for (size_t i = 0; i < constructor_count; i++) { + void (*ptr)(void) = (void(*)(void))(__init_array_start[i]); + ptr(); + } + } +*/ +} + +namespace mlibc { + +void parse_exec_stack(void *opaque_sp, exec_stack_data *data) { + auto sp = reinterpret_cast<uintptr_t *>(opaque_sp); + data->argc = *sp++; + data->argv = reinterpret_cast<char **>(sp); + sp += data->argc; // Skip all arguments. + __ensure(!*sp); // Skip the terminating null element. + sp++; + data->envp = reinterpret_cast<char **>(sp); +} + +// TODO: This does not have to be here; we could also move it to options/internal. +void set_startup_data(int argc, char **argv, char **envp) { + if(argc) { + program_invocation_name = argv[0]; + + if(auto slash = strrchr(argv[0], '/'); slash) { + program_invocation_short_name = slash + 1; + }else{ + program_invocation_short_name = argv[0]; + } + } + + // Initialize environ. + // TODO: Copy the arguments instead of pointing to them? + auto ev = envp; + while(*ev) { + auto fail = mlibc::putenv(*ev); + __ensure(!fail); + ev++; + } +} + +} // namespace mlibc + diff --git a/lib/mlibc/options/elf/include/elf.h b/lib/mlibc/options/elf/include/elf.h new file mode 100644 index 0000000..68d70c2 --- /dev/null +++ b/lib/mlibc/options/elf/include/elf.h @@ -0,0 +1,667 @@ +#ifndef _ELF_H +#define _ELF_H + +#include <stdint.h> +#include <bits/inline-definition.h> +#include <abi-bits/auxv.h> + +#ifdef __cplusplus +extern "C" { +#endif + +// TODO: Convert the enums to #defines so that they work with #ifdef. + +#define ELFCLASS64 2 +#define ELFDATA2LSB 1 +#define ELFOSABI_SYSV 0 +#define EM_X86_64 62 + +#define SHF_WRITE 1 +#define SHF_ALLOC 2 +#define SHF_EXECINSTR 4 +#define SHF_STRINGS 32 +#define SHF_INFO_LINK 64 +#define SHF_TLS 1024 + +#define NT_AUXV 6 + +typedef uint64_t Elf64_Addr; +typedef uint64_t Elf64_Off; +typedef uint16_t Elf64_Half; +typedef uint32_t Elf64_Word; +typedef int32_t Elf64_Sword; +typedef uint64_t Elf64_Xword; +typedef int64_t Elf64_Sxword; +typedef uint16_t Elf64_Section; +typedef Elf64_Half Elf64_Versym; + +typedef uint32_t Elf32_Addr; +typedef uint32_t Elf32_Off; +typedef uint16_t Elf32_Half; +typedef uint32_t Elf32_Word; +typedef int32_t Elf32_Sword; +typedef uint64_t Elf32_Xword; +typedef int64_t Elf32_Sxword; +typedef uint16_t Elf32_Section; +typedef Elf32_Half Elf32_Versym; + +#define EI_NIDENT (16) + +typedef struct { + unsigned char e_ident[EI_NIDENT]; /* ELF identification */ + Elf32_Half e_type; /* Object file type */ + Elf32_Half e_machine; /* Machine type */ + Elf32_Word e_version; /* Object file version */ + Elf32_Addr e_entry; /* Entry point address */ + Elf32_Off e_phoff; /* Program header offset */ + Elf32_Off e_shoff; /* Section header offset */ + Elf32_Word e_flags; /* Processor-specific flags */ + Elf32_Half e_ehsize; /* ELF header size */ + Elf32_Half e_phentsize; /* Size of program header entry */ + Elf32_Half e_phnum; /* Number of program header entries */ + Elf32_Half e_shentsize; /* Size of section header entry */ + Elf32_Half e_shnum; /* Number of section header entries */ + Elf32_Half e_shstrndx; /* Section name string table index */ +} Elf32_Ehdr; + +typedef struct { + unsigned char e_ident[EI_NIDENT]; /* ELF identification */ + Elf64_Half e_type; /* Object file type */ + Elf64_Half e_machine; /* Machine type */ + Elf64_Word e_version; /* Object file version */ + Elf64_Addr e_entry; /* Entry point address */ + Elf64_Off e_phoff; /* Program header offset */ + Elf64_Off e_shoff; /* Section header offset */ + Elf64_Word e_flags; /* Processor-specific flags */ + Elf64_Half e_ehsize; /* ELF header size */ + Elf64_Half e_phentsize; /* Size of program header entry */ + Elf64_Half e_phnum; /* Number of program header entries */ + Elf64_Half e_shentsize; /* Size of section header entry */ + Elf64_Half e_shnum; /* Number of section header entries */ + Elf64_Half e_shstrndx; /* Section name string table index */ +} Elf64_Ehdr; + +typedef struct { + Elf32_Half vd_version; /* Version revision */ + Elf32_Half vd_flags; /* Version information */ + Elf32_Half vd_ndx; /* Version Index */ + Elf32_Half vd_cnt; /* Number of associated aux entries */ + Elf32_Word vd_hash; /* Version name hash value */ + Elf32_Word vd_aux; /* Offset in bytes to verdaux array */ + Elf32_Word vd_next; /* Offset in bytes to next verdef entry */ +} Elf32_Verdef; + +typedef struct { + Elf64_Half vd_version; /* Version revision */ + Elf64_Half vd_flags; /* Version information */ + Elf64_Half vd_ndx; /* Version Index */ + Elf64_Half vd_cnt; /* Number of associated aux entries */ + Elf64_Word vd_hash; /* Version name hash value */ + Elf64_Word vd_aux; /* Offset in bytes to verdaux array */ + Elf64_Word vd_next; /* Offset in bytes to next verdef entry */ +} Elf64_Verdef; + +typedef struct { + Elf32_Word vda_name; /* Version or dependency names */ + Elf32_Word vda_next; /* Offset in bytes to next verdaux entry */ +} Elf32_Verdaux; + +typedef struct { + Elf64_Word vda_name; /* Version or dependency names */ + Elf64_Word vda_next; /* Offset in bytes to next verdaux entry */ +} Elf64_Verdaux; + +typedef struct { + Elf64_Half vn_version; + Elf64_Half vn_cnt; + Elf64_Word vn_file; + Elf64_Word vn_aux; + Elf64_Word vn_next; +} Elf64_Verneed; + +typedef struct { + Elf64_Word vna_hash; + Elf64_Half vna_flags; + Elf64_Half vna_other; + Elf64_Word vna_name; + Elf64_Word vna_next; +} Elf64_Vernaux; + +typedef struct { + Elf64_Xword m_value; + Elf64_Xword m_info; + Elf64_Xword m_poffset; + Elf64_Half m_repeat; + Elf64_Half m_stride; +} Elf64_Move; + +typedef struct { + Elf64_Word l_name; + Elf64_Word l_time_stamp; + Elf64_Word l_checksum; + Elf64_Word l_version; + Elf64_Word l_flags; +} Elf64_Lib; + +enum { + ET_NONE = 0, + ET_REL = 1, + ET_EXEC = 2, + ET_DYN = 3, + ET_CORE = 4, +}; + +enum { + SHN_UNDEF = 0, + SHN_ABS = 0xFFF1 +}; + +enum { + STN_UNDEF = 0, +}; + +typedef struct { + Elf32_Word st_name; + Elf32_Addr st_value; + Elf32_Word st_size; + unsigned char st_info; + unsigned char st_other; + Elf32_Section st_shndx; +} Elf32_Sym; + +typedef struct { + Elf64_Word st_name; + unsigned char st_info; + unsigned char st_other; + Elf64_Half st_shndx; + Elf64_Addr st_value; + Elf64_Xword st_size; +} Elf64_Sym; + +__MLIBC_INLINE_DEFINITION unsigned char ELF64_ST_BIND(unsigned char info) { + return info >> 4; +} +__MLIBC_INLINE_DEFINITION unsigned char ELF64_ST_TYPE(unsigned char info) { + return info & 0x0F; +} +__MLIBC_INLINE_DEFINITION unsigned char ELF64_ST_INFO(unsigned char bind, unsigned char type) { + return (bind << 4) | type; +} + +typedef struct { + Elf64_Half si_boundto; + Elf64_Half si_flags; +} Elf64_Syminfo; + +__MLIBC_INLINE_DEFINITION unsigned char ELF32_ST_BIND(unsigned char info) { + return info >> 4; +} +__MLIBC_INLINE_DEFINITION unsigned char ELF32_ST_TYPE(unsigned char info) { + return info & 0xF; +} +__MLIBC_INLINE_DEFINITION unsigned char ELF32_ST_INFO(unsigned char bind, unsigned char type) { + return (bind << 4) | (type & 0xF); +} + +enum { + STB_GLOBAL = 1, + STB_WEAK = 2, + STB_GNU_UNIQUE = 10, + STB_LOPROC = 13, + STB_HIPROC = 15 +}; + +enum { + STT_OBJECT = 1, + STT_FUNC = 2, + STT_TLS = 6, + STT_LOPROC = 13, + STT_HIPROC = 15 +}; + +enum { + R_X86_64_NONE = 0, + R_X86_64_64 = 1, + R_X86_64_PC32 = 2, + R_X86_64_PLT32 = 4, + R_X86_64_COPY = 5, + R_X86_64_GLOB_DAT = 6, + R_X86_64_JUMP_SLOT = 7, + R_X86_64_RELATIVE = 8, + R_X86_64_GOTPCREL = 9, + R_X86_64_32 = 10, + R_X86_64_32S = 11, + R_X86_64_PC16 = 13, + R_X86_64_PC8 = 15, + R_X86_64_DTPMOD64 = 16, + R_X86_64_DTPOFF64 = 17, + R_X86_64_TPOFF64 = 18, + R_X86_64_PC64 = 24, + R_X86_64_GOTPC32 = 26, + R_X86_64_TLSDESC = 36, + R_X86_64_IRELATIVE = 37, +}; + +enum { + R_386_NONE = 0, + R_386_32 = 1, + R_386_PC32 = 2, + R_386_COPY = 5, + R_386_GLOB_DAT = 6, + R_386_JMP_SLOT = 7, + R_386_RELATIVE = 8, + R_386_TLS_TPOFF = 14, + R_386_TLS_DTPMOD32 = 35, + R_386_TLS_DTPOFF32 = 36, + R_386_TLS_DESC = 41, + R_386_IRELATIVE = 42, +}; + +enum { + R_AARCH64_NONE = 0, + R_AARCH64_ABS64 = 257, + R_AARCH64_COPY = 1024, + R_AARCH64_GLOB_DAT = 1025, + R_AARCH64_JUMP_SLOT = 1026, + R_AARCH64_RELATIVE = 1027, + R_AARCH64_TLS_DTPREL64 = 1028, + R_AARCH64_TLS_DTPMOD64 = 1029, + R_AARCH64_TLS_TPREL64 = 1030, + R_AARCH64_TLSDESC = 1031, + R_AARCH64_IRELATIVE = 1032, +}; + +#define R_AARCH64_TLS_DTPREL R_AARCH64_TLS_DTPREL64 +#define R_AARCH64_TLS_DTPMOD R_AARCH64_TLS_DTPMOD64 +#define R_AARCH64_TLS_TPREL R_AARCH64_TLS_TPREL64 + +enum { + R_RISCV_NONE = 0, + R_RISCV_32 = 1, + R_RISCV_64 = 2, + R_RISCV_RELATIVE = 3, + R_RISCV_COPY = 4, + R_RISCV_JUMP_SLOT = 5, + R_RISCV_TLS_DTPMOD32 = 6, + R_RISCV_TLS_DTPMOD64 = 7, + R_RISCV_TLS_DTPREL32 = 8, + R_RISCV_TLS_DTPREL64 = 9, + R_RISCV_TLS_TPREL32 = 10, + R_RISCV_TLS_TPREL64 = 11, + R_RISCV_TLSDESC = 12, // currently a draft but looking good + R_RISCV_IRELATIVE = 58 +}; + +typedef struct { + Elf32_Addr r_offset; + Elf32_Word r_info; +} Elf32_Rel; + +typedef struct { + Elf64_Addr r_offset; + uint64_t r_info; +} Elf64_Rel; + +typedef struct { + Elf32_Addr r_offset; + Elf32_Word r_info; + Elf32_Sword r_addend; +} Elf32_Rela; + +typedef struct { + Elf64_Addr r_offset; + Elf64_Xword r_info; + Elf64_Sxword r_addend; +} Elf64_Rela; + +typedef Elf32_Word Elf32_Relr; +typedef Elf64_Xword Elf64_Relr; + +__MLIBC_INLINE_DEFINITION Elf64_Xword ELF64_R_SYM(Elf64_Xword info) { + return info >> 32; +} +__MLIBC_INLINE_DEFINITION Elf64_Xword ELF64_R_TYPE(Elf64_Xword info) { + return info & 0xFFFFFFFF; +} +__MLIBC_INLINE_DEFINITION Elf64_Xword ELF64_R_INFO(Elf64_Xword sym, Elf64_Xword type) { + return ((((Elf64_Xword)(sym)) << 32) + (type)); +} + +__MLIBC_INLINE_DEFINITION Elf32_Word ELF32_R_SYM(Elf32_Word info) { + return info >> 8; +} +__MLIBC_INLINE_DEFINITION Elf32_Word ELF32_R_TYPE(Elf32_Word info) { + return info & 0xFF; +} + +enum { + PT_NULL = 0, + PT_LOAD = 1, + PT_DYNAMIC = 2, + PT_INTERP = 3, + PT_NOTE = 4, + PT_SHLIB = 5, + PT_PHDR = 6, + PT_TLS = 7, + PT_NUM = 8, + PT_LOOS = 0x60000000, + PT_GNU_EH_FRAME = 0x6474E550, + PT_GNU_STACK = 0x6474E551, + PT_GNU_RELRO = 0x6474E552, + PT_GNU_PROPERTY = 0x6474E553, + PT_SUNWBSS = 0x6ffffffa, + PT_SUNWSTACK = 0x6ffffffb, + PT_HISUNW = 0x6fffffff, + PT_HIOS = 0x6fffffff, + PT_LOPROC = 0x70000000, + PT_RISCV_ATTRIBUTES = 0x70000003, + PT_HIPROC = 0x7fffffff, +}; + +enum { + PF_X = 1, + PF_W = 2, + PF_R = 4 +}; + +typedef struct { + Elf32_Word p_type; /* Type of segment */ + Elf32_Off p_offset; /* Offset in file */ + Elf32_Addr p_vaddr; /* Virtual address in memory */ + Elf32_Addr p_paddr; /* Reserved */ + Elf32_Word p_filesz; /* Size of segment in file */ + Elf32_Word p_memsz; /* Size of segment in memory */ + Elf32_Word p_flags; /* Segment attributes */ + Elf32_Word p_align; /* Alignment of segment */ +} Elf32_Phdr; + +typedef struct { + Elf64_Word p_type; /* Type of segment */ + Elf64_Word p_flags; /* Segment attributes */ + Elf64_Off p_offset; /* Offset in file */ + Elf64_Addr p_vaddr; /* Virtual address in memory */ + Elf64_Addr p_paddr; /* Reserved */ + Elf64_Xword p_filesz; /* Size of segment in file */ + Elf64_Xword p_memsz; /* Size of segment in memory */ + Elf64_Xword p_align; /* Alignment of segment */ +} Elf64_Phdr; + +enum { + DT_NULL = 0, + DT_NEEDED = 1, + DT_PLTRELSZ = 2, + DT_PLTGOT = 3, + DT_HASH = 4, + DT_STRTAB = 5, + DT_SYMTAB = 6, + DT_RELA = 7, + DT_RELASZ = 8, + DT_RELAENT = 9, + DT_STRSZ = 10, + DT_SYMENT = 11, + DT_INIT = 12, + DT_FINI = 13, + DT_SONAME = 14, + DT_RPATH = 15, + DT_SYMBOLIC = 16, + DT_REL = 17, + DT_RELSZ = 18, + DT_RELENT = 19, + DT_TEXTREL = 22, + DT_BIND_NOW = 24, + DT_INIT_ARRAY = 25, + DT_FINI_ARRAY = 26, + DT_INIT_ARRAYSZ = 27, + DT_FINI_ARRAYSZ = 28, + DT_RUNPATH = 29, + DT_PLTREL = 20, + DT_DEBUG = 21, + DT_JMPREL = 23, + DT_FLAGS = 30, + DT_PREINIT_ARRAY = 32, + DT_PREINIT_ARRAYSZ = 33, + DT_RELRSZ = 35, + DT_RELR = 36, + DT_RELRENT = 37, + DT_LOOS = 0x6000000d, + DT_HIOS = 0x6ffff000, + DT_GNU_HASH = 0x6ffffef5, + DT_TLSDESC_PLT = 0x6ffffef6, + DT_TLSDESC_GOT = 0x6ffffef7, + DT_VERSYM = 0x6ffffff0, + DT_RELACOUNT = 0x6ffffff9, + DT_RELCOUNT = 0x6ffffffa, + DT_FLAGS_1 = 0x6ffffffb, + DT_VERDEF = 0x6ffffffc, + DT_VERDEFNUM = 0x6ffffffd, + DT_VERNEED = 0x6ffffffe, + DT_VERNEEDNUM = 0x6fffffff +}; + +enum { + // For DT_FLAGS. + DF_SYMBOLIC = 0x02, + DF_TEXTREL = 0x04, + DF_BIND_NOW = 0x08, + DF_STATIC_TLS = 0x10, + + // For DT_FLAGS_1. + DF_1_NOW = 0x00000001, + DF_1_NODELETE = 0x00000008, + DF_1_PIE = 0x08000000 +}; + +// Valid values for note segment descriptor files for core files +#define NT_PRSTATUS 1 +#define NT_FPREGSET 2 +#define NT_PRPSINFO 3 + +// Build ID bits as generated by ld --build-id +#define NT_GNU_BUILD_ID 3 + +typedef struct { + Elf32_Sword d_tag; + union { + Elf32_Word d_val; + Elf32_Addr d_ptr; + } d_un; +} Elf32_Dyn; + +typedef struct { + Elf64_Sxword d_tag; + union { + Elf64_Xword d_val; + Elf64_Addr d_ptr; + } d_un; +} Elf64_Dyn; + +typedef struct { + Elf32_Word sh_name; + Elf32_Word sh_type; + Elf32_Word sh_flags; + Elf32_Addr sh_addr; + Elf32_Off sh_offset; + Elf32_Word sh_size; + Elf32_Word sh_link; + Elf32_Word sh_info; + Elf32_Word sh_addralign; + Elf32_Word sh_entsize; +} Elf32_Shdr; + +typedef struct { + Elf64_Word sh_name; + Elf64_Word sh_type; + Elf64_Xword sh_flags; + Elf64_Addr sh_addr; + Elf64_Off sh_offset; + Elf64_Xword sh_size; + Elf64_Word sh_link; + Elf64_Word sh_info; + Elf64_Xword sh_addralign; + Elf64_Xword sh_entsize; +} Elf64_Shdr; + +typedef struct { + uint64_t a_type; + union { + uint64_t a_val; + } a_un; +} Elf64_auxv_t; + +typedef struct { + uint32_t a_type; + union { + uint32_t a_val; + } a_un; +} Elf32_auxv_t; + +typedef struct { + Elf32_Word n_namesz; + Elf32_Word n_descsz; + Elf32_Word n_type; +} Elf32_Nhdr; + +typedef struct { + Elf64_Word n_namesz; + Elf64_Word n_descsz; + Elf64_Word n_type; +} Elf64_Nhdr; + +/* ST_TYPE (subfield of st_info) values (symbol type) */ +#define STT_NOTYPE 0 +#define STT_OBJECT 1 +#define STT_FUNC 2 +#define STT_SECTION 3 +#define STT_FILE 4 + +/* ST_BIND (subfield of st_info) values (symbol binding) */ +#define STB_LOCAL 0 +#define STB_GLOBAL 1 +#define STB_WEAK 2 + +/* sh_type (section type) values */ +#define SHT_NULL 0 +#define SHT_PROGBITS 1 +#define SHT_SYMTAB 2 +#define SHT_STRTAB 3 +#define SHT_RELA 4 +#define SHT_HASH 5 +#define SHT_DYNAMIC 6 +#define SHT_NOTE 7 +#define SHT_NOBITS 8 +#define SHT_REL 9 +#define SHT_DYNSYM 11 +#define SHT_INIT_ARRAY 14 +#define SHT_FINI_ARRAY 15 +#define SHT_SYMTAB_SHNDX 18 + +/* special section indices */ +#define SHN_UNDEF 0 +#define SHN_LORESERVE 0xff00 +#define SHN_COMMON 0xfff2 +#define SHN_XINDEX 0xffff +#define SHN_HIRESERVE 0xff00 + +/* values for e_machine */ +#define EM_NONE 0 +#define EM_M32 1 +#define EM_SPARC 2 +#define EM_386 3 +#define EM_68K 4 +#define EM_MIPS 8 +#define EM_PARISC 15 +#define EM_PPC 20 +#define EM_PPC64 21 +#define EM_S390 22 +#define EM_ARM 40 +#define EM_SH 42 +#define EM_SPARCV9 43 +#define EM_IA_64 50 +#define EM_X86_64 62 +#define EM_BLACKFIN 106 +#define EM_AARCH64 183 +#define EM_RISCV 243 + +/* Linux notes this value as being interim; however applications are using this (Qt6), so we define it here. */ +#define EM_ALPHA 0x9026 + +/* values for e_version */ +#define EV_NONE 0 +#define EV_CURRENT 1 +#define EV_NUM 2 + +/* e_indent constants */ +#define EI_MAG0 0 +#define ELFMAG0 0x7f + +#define EI_MAG1 1 +#define ELFMAG1 'E' + +#define EI_MAG2 2 +#define ELFMAG2 'L' + +#define EI_MAG3 3 +#define ELFMAG3 'F' + +#define ELFMAG "\177ELF" +#define SELFMAG 4 + +#define EI_CLASS 4 +#define ELFCLASSNONE 0 +#define ELFCLASS32 1 +#define ELFCLASS64 2 +#define ELFCLASSNUM 3 + +#define EI_DATA 5 +#define ELFDATANONE 0 +#define ELFDATA2LSB 1 +#define ELFDATA2MSB 2 +#define ELFDATANUM 3 + +#define EI_VERSION 6 + +#define EI_OSABI 7 +#define ELFOSABI_HPUX 1 +#define ELFOSABI_NETBSD 2 +#define ELFOSABI_GNU 3 +#define ELFOSABI_LINUX ELFOSABI_GNU +#define ELFOSABI_SOLARIS 6 +#define ELFOSABI_AIX 7 +#define ELFOSABI_IRIX 8 +#define ELFOSABI_FREEBSD 9 +#define ELFOSABI_OPENBSD 12 + +#define EI_ABIVERSION 8 + +#define ELF_NOTE_GNU "GNU" + +/* Values for a_type + * these are standard values and shared across at least glibc, musl and freebsd + */ + +#define AT_NULL 0 +#define AT_IGNORE 1 +#define AT_EXECFD 2 +#define AT_PHDR 3 +#define AT_PHENT 4 +#define AT_PHNUM 5 +#define AT_PAGESZ 6 +#define AT_BASE 7 +#define AT_FLAGS 8 +#define AT_ENTRY 9 +#define AT_NOTELF 10 +#define AT_UID 11 +#define AT_EUID 12 +#define AT_GID 13 +#define AT_EGID 14 + +/* rtdl requires presence of some a_type (AT_*) values that are not standardized in the ELF spec */ +#if !defined(AT_EXECFN) || !defined(AT_RANDOM) || !defined(AT_SECURE) +#error "sysdeps' auxv.h is missing some defines that are required for rtdl operation" +#endif + +#ifdef __cplusplus +} +#endif + +#endif // _ELF_H diff --git a/lib/mlibc/options/elf/include/link.h b/lib/mlibc/options/elf/include/link.h new file mode 100644 index 0000000..65d54b9 --- /dev/null +++ b/lib/mlibc/options/elf/include/link.h @@ -0,0 +1,58 @@ +#ifndef _LINK_H +#define _LINK_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include <elf.h> +#include <stddef.h> + +#if defined(__x86_64__) || defined(__aarch64__) \ + || (defined(__riscv) && __riscv_xlen == 64) +# define ElfW(type) Elf64_ ## type +#elif defined(__i386__) +# define ElfW(type) Elf32_ ## type +#else +# error Unknown architecture +#endif + +struct dl_phdr_info { + ElfW(Addr) dlpi_addr; + const char *dlpi_name; + const ElfW(Phdr) *dlpi_phdr; + ElfW(Half) dlpi_phnum; + unsigned long long int dlpi_adds; + unsigned long long int dlpi_subs; + size_t dlpi_tls_modid; + void *dlpi_tls_data; +}; + +struct link_map { + Elf64_Addr l_addr; + char *l_name; + ElfW(Dyn) *l_ld; + struct link_map *l_next, *l_prev; +}; + +struct r_debug { + int r_version; + struct link_map *r_map; + Elf64_Addr r_brk; + enum { RT_CONSISTENT, RT_ADD, RT_DELETE } r_state; + Elf64_Addr r_ldbase; +}; + +#ifndef __MLIBC_ABI_ONLY + +int dl_iterate_phdr(int (*callback)(struct dl_phdr_info*, size_t, void*), void* data); + +extern ElfW(Dyn) _DYNAMIC[]; + +#endif /* !__MLIBC_ABI_ONLY */ + +#ifdef __cplusplus +} +#endif + +#endif // _LINK_H diff --git a/lib/mlibc/options/elf/include/mlibc/elf/startup.h b/lib/mlibc/options/elf/include/mlibc/elf/startup.h new file mode 100644 index 0000000..7e8a8d7 --- /dev/null +++ b/lib/mlibc/options/elf/include/mlibc/elf/startup.h @@ -0,0 +1,28 @@ +#ifndef MLIBC_ELF_STARTUP +#define MLIBC_ELF_STARTUP + +#ifndef __MLIBC_ABI_ONLY + +void __mlibc_run_constructors(); + +#endif /* !__MLIBC_ABI_ONLY */ + +namespace mlibc { + +struct exec_stack_data { + int argc; + char **argv; + char **envp; +}; + +#ifndef __MLIBC_ABI_ONLY + +void parse_exec_stack(void *sp, exec_stack_data *data); + +void set_startup_data(int argc, char **argv, char **envp); + +#endif /* !__MLIBC_ABI_ONLY */ + +} // namespace mlibc + +#endif // MLIBC_ELF_STARTUP diff --git a/lib/mlibc/options/elf/meson.build b/lib/mlibc/options/elf/meson.build new file mode 100644 index 0000000..b096801 --- /dev/null +++ b/lib/mlibc/options/elf/meson.build @@ -0,0 +1,11 @@ +libc_sources += files( + 'generic/startup.cpp', + 'generic/phdr.cpp', +) + +if not no_headers + install_headers( + 'include/elf.h', + 'include/link.h', + ) +endif |