1// SPDX-License-Identifier: GPL-3.0-or-later
2
3#pragma once
4
5#include "mos/tasks/process.hpp"
6#include "mos/tasks/task_types.hpp"
7
8#include <elf.h>
9#include <mos/types.hpp>
10#include <mos/vector.hpp>
11
12typedef enum
13{
14 ELF_ENDIANNESS_INVALID = 0,
15 ELF_ENDIANNESS_LSB = 1,
16 ELF_ENDIANNESS_MSB = 2,
17} elf_endianness;
18
19#if MOS_LITTLE_ENDIAN
20#define ELF_ENDIANNESS_MOS_DEFAULT ELF_ENDIANNESS_LSB
21#else
22#define ELF_ENDIANNESS_MOS_DEFAULT ELF_ENDIANNESS_MSB
23#endif
24
25typedef struct
26{
27 char magic[4];
28 u32 bits : 8;
29 u32 endianness : 8;
30 u32 version : 8;
31 u32 osabi : 8;
32 u8 abiversion : 8;
33 u8 __padding[7];
34} elf_identity_t;
35
36MOS_STATIC_ASSERT(sizeof(elf_identity_t) == 16, "elf_identity_t has wrong size");
37
38typedef struct
39{
40 elf_identity_t identity;
41 int object_type : 16;
42 int machine_type : 16;
43
44 u32 version;
45
46 ptr_t entry_point;
47 size_t ph_offset;
48 size_t sh_offset;
49
50 u32 flags;
51 u16 header_size;
52
53 struct
54 {
55 u16 entry_size, count;
56 } __packed ph, sh;
57
58 u16 sh_strtab_index;
59} __packed elf_header_t;
60
61typedef enum
62{
63 ELF_PT_NULL = 0, // Unused entry
64 ELF_PT_LOAD = 1, // Loadable segment
65 ELF_PT_DYNAMIC = 2, // Dynamic linking information
66 ELF_PT_INTERP = 3, // Interpreter information
67 ELF_PT_NOTE = 4, // Auxiliary information
68 ELF_PT_SHLIB = 5, // reserved
69 ELF_PT_PHDR = 6, // Segment containing program header table
70 ELF_PT_TLS = 7, // Thread-local storage segment
71
72 _ELF_PT_COUNT,
73
74 ELF_PT_OS_LOW = 0x60000000, // reserved
75 ELF_PT_OS_HIGH = 0x6fffffff, // reserved
76 ELF_PT_PROCESSOR_LO = 0x70000000, // reserved
77 ELF_PT_PROCESSOR_HI = 0x7fffffff, // reserved
78} elf_program_header_type;
79
80typedef enum
81{
82 ELF_PF_X = 1 << 0, // Executable
83 ELF_PF_W = 1 << 1, // Writable
84 ELF_PF_R = 1 << 2, // Readable
85} elf_ph_flags;
86
87typedef struct elf_program_hdr_t
88{
89 elf_program_header_type header_type;
90 elf_ph_flags __p_flags; // Segment independent flags (64-bit only)
91 ptr_t data_offset; // Offset of the segment in the file
92 ptr_t vaddr; // Virtual address of the segment
93 ptr_t _reserved; // reserved
94 ptr_t size_in_file; // Size of the segment in the file (may be 0)
95 ptr_t size_in_mem; // Size of the segment in memory (may be 0)
96 ptr_t required_alignment;
97
98 Flags<elf_ph_flags> flags() const
99 {
100 return __p_flags;
101 }
102} __packed elf_program_hdr_t;
103
104struct elf_startup_info_t
105{
106 mos::string_view invocation;
107 mos::vector<Elf64_auxv_t> auxv;
108 mos::vector<mos::string> argv;
109 mos::vector<mos::string> envp;
110
111 void AddAuxvEntry(u64 type, u64 val)
112 {
113 auxv.push_back(value: Elf64_auxv_t{ .a_type = type, .a_un = { .a_val = val } });
114 }
115};
116
117[[nodiscard]] bool elf_read_and_verify_executable(FsBaseFile *file, elf_header_t *header);
118[[nodiscard]] bool elf_do_fill_process(Process *proc, FsBaseFile *file, elf_header_t elf, elf_startup_info_t *info);
119Process *elf_create_process(mos::string_view path, Process *parent, const mos::vector<mos::string> &argv, const mos::vector<mos::string> &envp, const stdio_t *ios);
120