51 const size_t read = file->
pread(buf,
size, offset);
86 const void *stack_envp[info->
envp.size() + 1];
87 const void *stack_argv[info->
argv.size() + 1];
90 size_t stack_size = 0;
91 stack_size +=
sizeof(
uintn);
94 for (
const auto &env : info->
envp)
95 stack_size += env.size() + 1;
97 for (
const auto &arg : info->
argv)
98 stack_size += arg.size() + 1;
100 stack_size +=
sizeof(Elf64_auxv_t) * (info->
auxv.
size() + 2);
101 stack_size +=
sizeof(stack_envp);
102 stack_size +=
sizeof(stack_argv);
103 stack_size +=
sizeof(
uintn);
106 const size_t aligned_stack_size =
ALIGN_UP(stack_size, 16);
117 if (info->
envp.empty())
120 for (
int i = info->
envp.size() - 1; i >= 0; i--)
122 const size_t len = info->
envp[i].size() + 1;
127 stack_envp[info->
envp.size()] =
NULL;
130 if (info->
argv.empty())
133 for (
int i = info->
argv.size() - 1; i >= 0; i--)
135 const size_t len = info->
argv[i].size() + 1;
140 stack_argv[info->
argv.size()] =
NULL;
161 const VMFlags flags = [pflags = ph->
flags()]()
177 const ptr_t map_start = map_bias + aligned_vaddr;
178 dInfo2<elf> <<
" mapping " << npages <<
" pages at " << map_start <<
" (bias at " << map_bias <<
") from offset " << aligned_size <<
"...";
195 if (interp_file.isErr())
203 mEmerg <<
"failed to verify ELF header for '" <<
dentry_name(interp_file->dentry) <<
"'";
204 interp_file->unref();
210 for (
size_t i = 0; i < elf.
ph.
count; i++)
215 mEmerg <<
"failed to read program header " << i <<
" for '" <<
dentry_name(interp_file->dentry) <<
"'";
216 interp_file->unref();
228 interp_file->unref();
247 ptrdiff_t map_bias = 0;
249 bool has_interpreter =
false;
250 ptr_t interp_entrypoint = 0;
251 ptr_t auxv_phdr_vaddr =
false;
253 for (
size_t i = 0; i < header.
ph.
count; i++)
278 has_interpreter =
true;
280 if (!interp_entrypoint)
282 dInfo2<elf> <<
"failed to map interpreter '" << interp_name <<
"'";
300 auxv_phdr_vaddr = ph.
vaddr;
322 info->
AddAuxvEntry(AT_PHDR, map_bias + auxv_phdr_vaddr);
329 ptr_t user_argv, user_envp;
334 has_interpreter ? interp_entrypoint : header.
entry_point,
335 main_thread->u_stack.head,
#define MOS_ASSERT_X(cond, msg,...)
#define mos_warn(fmt,...)
#define MOS_ELF_INTERPRETER_BASE_OFFSET
const CharT * data() const
const Char * c_str() const
auto size() const noexcept
auto data(this auto &Self) noexcept
Process * 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)
static ptr_t elf_determine_loadbias(elf_header_t *elf)
__nodiscard bool elf_do_fill_process(Process *proc, FsBaseFile *file, elf_header_t header, elf_startup_info_t *info)
static ptr_t elf_map_interpreter(const char *path, MMContext *mm)
static bool elf_verify_header(const elf_header_t *header)
static void elf_map_segment(const elf_program_hdr_t *const ph, ptr_t map_bias, MMContext *mm, FsBaseFile *file)
static void elf_setup_main_thread(Thread *thread, elf_startup_info_t *const info, ptr_t *const out_pargv, ptr_t *const out_penvp)
static bool elf_read_file(FsBaseFile *file, void *buf, off_t offset, size_t size)
static bool elf_fill_process(Process *proc, FsBaseFile *file, mos::string_view path, const mos::vector< mos::string > &argv, const mos::vector< mos::string > &envp)
bool elf_read_and_verify_executable(FsBaseFile *file, elf_header_t *header)
#define ELF_ENDIANNESS_MOS_DEFAULT
#define stack_push_val(stack, val)
MOSAPI void * stack_push(downwards_stack_t *stack, const void *data, size_t size)
MOSAPI s32 strncmp(const char *str1, const char *str2, size_t n)
MOSAPI void(1, 2) fatal_abort(const char *fmt
__nodiscard MMContext * mm_switch_context(MMContext *new_ctx)
PtrResult< FsBaseFile > vfs_openat(int fd, mos::string_view path, OpenFlags flags)
Open a file at a given path.
ptr_t mmap_file(MMContext *ctx, ptr_t hint_addr, MMapFlags flags, VMFlags VMFlags, size_t n_pages, IO *io, off_t offset)
Map a file into the current process's address space.
#define MOS_IN_RANGE(addr, start, end)
#define ALIGN_UP_TO_PAGE(addr)
#define ALIGN_DOWN_TO_PAGE(addr)
#define MOS_STATIC_ASSERT
#define ALIGN_UP(addr, size)
basic_string_view< char > string_view
void process_exit(Process *&&proc, u8 exit_code, signal_t signal)
Process * process_new(Process *parelagsnt, mos::string_view name, const stdio_t *ios)
#define memzero(ptr, size)
void scheduler_add_thread(Thread *thread)
Add a thread to the scheduler, so that it can be scheduled.
virtual size_t pread(void *buf, size_t count, off_t offset) final
downwards_stack_t u_stack
user-mode stack
elf_program_header_type header_type
Flags< elf_ph_flags > flags() const
mos::vector< mos::string > envp
mos::string_view invocation
mos::vector< mos::string > argv
mos::vector< Elf64_auxv_t > auxv
void AddAuxvEntry(u64 type, u64 val)
A wrapper type for the standard I/O streams.
Thread * thread_complete_init(Thread *thread)
mos::string dentry_name(const dentry_t *dentry)