[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[tyndur-devel] [PATCH 1/2] init: ELF-Loader aus der libc benutzen
* init: ELF-Loader aus der libc benutzen statt eigener Implementierung.
Die Loader duerften momentan in etwa gleich kaputt sein.
Signed-off-by: Kevin Wolf <kevin@xxxxxxxxxx>
---
src/modules/init/init.c | 114 ++++---------------------------------------
src/modules/init/loader.c | 118 +++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 128 insertions(+), 104 deletions(-)
create mode 100644 src/modules/init/loader.c
diff --git a/src/modules/init/init.c b/src/modules/init/init.c
index 475d602..dace629 100644
--- a/src/modules/init/init.c
+++ b/src/modules/init/init.c
@@ -76,7 +76,8 @@ void rpc_loadelf(pid_t pid, dword correlation_id, size_t data_size, void* data);
void rpc_reopen_stdio(pid_t pid, dword cid, size_t size, void* data);
void load_modules(init_module_list_t* modules);
-bool load_single_module(Elf32_Ehdr* elf_header, char* args, pid_t parent_pid);
+pid_t load_single_module(void* image, size_t image_size, char* args,
+ pid_t parent_pid) ;
bool start_program(char* path, char* args, pid_t parent_pid);
extern void init_sync_messages(void);
@@ -351,109 +352,13 @@ void load_modules(init_module_list_t* modules)
for(i = 0; i < modules->count; i++)
{
//printf("Modul %d: %s\n", i, modules->modules[i].cmdline);
- load_single_module((Elf32_Ehdr*) modules->modules[i].start, modules->modules[i].cmdline, 0);
+ load_single_module((Elf32_Ehdr*) modules->modules[i].start,
+ modules->modules[i].size, modules->modules[i].cmdline, 0);
mem_free(modules->modules[i].start, modules->modules[i].size);
//msleep(50); // Damit die Meldungen nicht durcheinandergeraten
}
}
-/**
- * Der ELF-Loader (noch Total Kaputt)
- */
-pid_t load_single_module(Elf32_Ehdr* elf_header, char* args, pid_t parent_pid)
-{
- Elf32_Phdr* program_header;
- dword i, j;
- pid_t pid;
-
- //Liste mit den Programm-Headern. Wird benutzt um auch programme laden zu koennen, die nicht
- list_t* pheader_list = list_create();
-
- pid = 0;
- if (elf_header->e_magic == ELF_MAGIC)
- {
- program_header = (Elf32_Phdr *) ((dword) elf_header + elf_header->e_phoff);
- //Zuerst den Bereich mit dem entry-point suchen
- for (j = 0; j < 2; j++)
- {
- for (i = 0; i < elf_header->e_phnum; i++)
- {
- // Im ersten durchgang alles ausser dem Bereich mit dem entry-Point pushe, damit er zu oberst ist
- if((j == 1) && ((elf_header->e_entry >= program_header[i].p_vaddr) && (elf_header->e_entry <= program_header[i].p_vaddr + program_header[i].p_memsz)))
- {
- pheader_list = list_push(pheader_list, (void*)&(program_header[i]));
- }
- else if((j == 0) && !((elf_header->e_entry >= program_header[i].p_vaddr) && (elf_header->e_entry <= program_header[i].p_vaddr + program_header[i].p_memsz)))
- {
- pheader_list = list_push(pheader_list, (void*)&(program_header[i]));
- }
- }
- }
-
- while(list_is_empty(pheader_list) == FALSE)
- {
- //Den naechsten Bereich aus der Liste holen
- program_header = (Elf32_Phdr*) list_pop(pheader_list);
-
- if (program_header->p_type == 1)
- {
- if ((elf_header->e_entry >= program_header->p_vaddr) && (elf_header->e_entry <= program_header->p_vaddr + program_header->p_memsz))
- {
- if(pid != 0)
- {
- unblock_process(pid);
- pid = 0;
- }
- pid = create_process(elf_header->e_entry, 0, args, parent_pid);
- //printf("[ INIT ] Erstelle Prozess PID=%d entry=0x%08x\n", pid, elf_header->e_entry);
- }
- else if (pid == 0)
- {
- // FIXME
- printf("Kein Task: phdr->vaddr = %x, ehdr->entry = %x\nDas Modul ist entweder beschaedigt oder wird von diesem Loader nicht unterstuetzt (Kein Entry Point wurde gefunden :-S)\n", program_header->p_vaddr, elf_header->e_entry);
- continue;
- }
-
- dword page_offset = program_header->p_vaddr % 0x1000;
-
- // Groesse des benoetigten Speicherblocks berechnen
- size_t mem_size = program_header->p_memsz;
- mem_size = PAGE_ALIGN_ROUND_UP(mem_size + page_offset);
-
-
- void* mem_image = mem_allocate(mem_size, 0);
-
- // FIXME: Hier koennte man noch ein Bisschen Zeit sparen indem
- // nur die letzten paar Bytes auf 0 gesetzt werden. Aber dann
- // kriege ich es garantiert hin, entweder zuwenig oder zuviel
- // zu nullen. ;-)
- memset(mem_image, 0, mem_size);
-
- // printf(" Kopiere 0x%08x Bytes nach 0x%08x\n", program_header->p_filesz, program_header->p_vaddr + page_offset);
- // Daten kopieren
- memcpy((void*) ((dword) mem_image + page_offset), (void*) ((dword) elf_header + program_header->p_offset), program_header->p_filesz);
-
- // Pages in den Prozess mappen
- init_child_page (pid, (void*) (program_header->p_vaddr), mem_image, mem_size);
- }
- }
-
- }
- else
- {
- printf("ELF-Magic ungueltig (0x%x)\n",elf_header->e_magic);
- return 0;
- }
-
-
- if(pid != 0)
- {
- unblock_process(pid);
- }
-
- return pid;
-}
-
size_t ainflate(void* src, size_t len, void** dest_ptr)
{
int ret = 0;
@@ -537,6 +442,7 @@ pid_t start_program(char* path, char* args, pid_t parent_pid)
}
void* buffer = NULL;
+ size_t buffer_size = 0;
long size = 0;
fseek(f, 0, SEEK_END);
@@ -558,10 +464,9 @@ pid_t start_program(char* path, char* args, pid_t parent_pid)
byte* in_buffer = malloc(pages * 4096);
fread(in_buffer, 1, size, f);
- size_t length = ainflate(in_buffer, size, &buffer);
+ buffer_size = ainflate(in_buffer, size, &buffer);
free(in_buffer);
- if(length == 0)
- {
+ if (buffer_size == 0) {
return FALSE;
}
}
@@ -599,12 +504,13 @@ pid_t start_program(char* path, char* args, pid_t parent_pid)
}
else
{
- buffer = malloc(pages * 4096);
+ buffer_size = pages * 4096;
+ buffer = malloc(buffer_size);
fread(buffer, 1, size, f);
}
fclose(f);
- pid = load_single_module((Elf32_Ehdr*) buffer, args, parent_pid);
+ pid = load_single_module(buffer, buffer_size, args, parent_pid);
free(buffer);
return pid;
}
diff --git a/src/modules/init/loader.c b/src/modules/init/loader.c
new file mode 100644
index 0000000..9e7d06a
--- /dev/null
+++ b/src/modules/init/loader.c
@@ -0,0 +1,118 @@
+/*
+ * Copyright (c) 2010 The tyndur Project. All rights reserved.
+ *
+ * This code is derived from software contributed to the tyndur Project
+ * by Kevin Wolf.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the tyndur Project
+ * and its contributors.
+ * 4. Neither the name of the tyndur Project nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <syscall.h>
+#include <loader.h>
+#include <lock.h>
+
+static struct {
+ pid_t pid;
+ char* args;
+ pid_t parent_pid;
+ lock_t lock;
+} loader_state;
+
+/**
+ * Speicher allozieren um ihn spaeter in einen neuen Prozess zu mappen. Diese
+ * Funktion sollte nicht fuer "normale" Allokationen benutzt werden, da immer
+ * ganze Pages alloziert werden.
+ *
+ * @param size minimale Groesse des Bereichs
+ *
+ * @return Adresse, oder NULL falls ein Fehler aufgetreten ist
+ */
+vaddr_t loader_allocate_mem(size_t size)
+{
+ return mem_allocate(size, 0);
+}
+
+/**
+ * Ein Stueck Speicher in den Prozess mappen. Dieser darf dazu noch nicht
+ * gestartet sein. Der Speicher muss zuerst mit loader_allocate_mem alloziert
+ * worden sein, denn sonst kann nicht garantiert werden, dass der Speicher
+ * uebertragen werden kann.
+ *
+ * @param process PID des Prozesses
+ * @param dest_address Adresse an die der Speicher im Zielprozess soll
+ * @param src_address Adresse im aktuellen Kontext die uebetragen werden soll
+ * @param size Groesse des Speicherbereichs in Bytes
+ *
+ * @return TRUE, wenn der bereich gemappt wurde, FALSE sonst
+ */
+bool loader_assign_mem(pid_t process, vaddr_t dest_address,
+ vaddr_t src_address, size_t size)
+{
+ init_child_page(loader_state.pid, dest_address, src_address, size);
+ return TRUE;
+}
+
+
+/**
+ * Erstellt einen neuen Thread.
+ *
+ * @param process PID
+ * @param address Einsprungsadresse des Threads
+ *
+ * @return bool TRUE, wenn der Thread erstellt wurde, FALSE sonst
+ */
+bool loader_create_thread(pid_t process, vaddr_t address)
+{
+ loader_state.pid = create_process((uintptr_t) address, 0,
+ loader_state.args, loader_state.parent_pid);
+ return loader_state.pid != 0;
+}
+
+/**
+ * Erstellt einen neuen Prozess aus einer ELF-Datei
+ */
+pid_t load_single_module(void* image, size_t image_size, char* args,
+ pid_t parent_pid)
+{
+ p();
+ lock(&loader_state.lock);
+
+ loader_state.args = args;
+ loader_state.parent_pid = parent_pid;
+ if (!loader_elf32_load_image(0, image, image_size)) {
+ loader_state.pid = 0;
+ goto fail;
+ }
+ unblock_process(loader_state.pid);
+
+fail:
+ unlock(&loader_state.lock);
+ v();
+ return loader_state.pid;
+}
--
1.6.0.2