[haiku-commits] BRANCH xyzzy-github.x86_64 - src/system/boot/loader headers/private/kernel/boot

  • From: xyzzy-github.x86_64 <community@xxxxxxxxxxxx>
  • To: haiku-commits@xxxxxxxxxxxxx
  • Date: Sat, 23 Jun 2012 13:48:59 +0200 (CEST)

added 1 changeset to branch 'refs/remotes/xyzzy-github/x86_64'
old head: 3a2a3367dc9bec2a5fbcd4ac849da6ac65e74e79
new head: ccadfaeeb577eb5f129adcc1441b92aaf9f5e443

----------------------------------------------------------------------------

ccadfae: Changed the boot ELF code to use templates and added ELF64 support.
  
  The actual implementation of the ELF loading methods have been put into
  an ELFLoader template class that takes a single template parameter, which
  is a structure containing all the necessary ELF typedefs. It's a bit
  verbose, but I thought it was a neater solution than using a bunch of
  standalone functions with a huge number of template parameters. There is
  no change to code outside of elf.cpp, the ELF32/ELF64 differences are
  handled internally.

                                      [ Alex Smith <alex@xxxxxxxxxxxxxxxx> ]

----------------------------------------------------------------------------

Commit:      ccadfaeeb577eb5f129adcc1441b92aaf9f5e443

Author:      Alex Smith <alex@xxxxxxxxxxxxxxxx>
Date:        Sat Jun 23 11:05:16 2012 UTC

----------------------------------------------------------------------------

6 files changed, 411 insertions(+), 302 deletions(-)
headers/private/kernel/boot/arch.h  |   21 +-
headers/private/kernel/boot/elf.h   |   19 +-
headers/private/system/elf_common.h |    8 -
src/system/boot/loader/Jamfile      |    4 +-
src/system/boot/loader/elf.cpp      |  654 ++++++++++++++++++-------------
src/system/boot/loader/elf.h        |    7 +-

----------------------------------------------------------------------------

diff --git a/headers/private/kernel/boot/arch.h 
b/headers/private/kernel/boot/arch.h
index 8642efe..2f4be42 100644
--- a/headers/private/kernel/boot/arch.h
+++ b/headers/private/kernel/boot/arch.h
@@ -5,24 +5,21 @@
 #ifndef KERNEL_BOOT_ARCH_H
 #define KERNEL_BOOT_ARCH_H
 
+
 #include <SupportDefs.h>
 #include <boot/elf.h>
 
 
-#ifdef __cplusplus
-extern "C" {
-#endif
-
 /* ELF support */
 
-extern status_t boot_arch_elf_relocate_rel(preloaded_elf32_image *image,
-       struct Elf32_Rel *rel, int rel_len);
-extern status_t boot_arch_elf_relocate_rela(preloaded_elf32_image *image,
-       struct Elf32_Rela *rel, int rel_len);
-
+extern status_t boot_arch_elf_relocate_rel(preloaded_elf32_image* image,
+       struct Elf32_Rel* rel, int rel_len);
+extern status_t boot_arch_elf_relocate_rel(preloaded_elf64_image* image,
+       struct Elf64_Rel* rel, int rel_len);
+extern status_t boot_arch_elf_relocate_rela(preloaded_elf32_image* image,
+       struct Elf32_Rela* rel, int rel_len);
+extern status_t boot_arch_elf_relocate_rela(preloaded_elf64_image* image,
+       struct Elf64_Rela* rel, int rel_len);
 
-#ifdef __cplusplus
-}
-#endif
 
 #endif /* KERNEL_BOOT_ARCH_H */
diff --git a/headers/private/kernel/boot/elf.h 
b/headers/private/kernel/boot/elf.h
index 1ef93c2..6c07ebc 100644
--- a/headers/private/kernel/boot/elf.h
+++ b/headers/private/kernel/boot/elf.h
@@ -1,7 +1,8 @@
 /*
-** Copyright 2003-2004, Axel Dörfler, axeld@xxxxxxxxxxxxxxxxx All rights 
reserved.
-** Distributed under the terms of the OpenBeOS License.
-*/
+ * Copyright 2003-2004, Axel Dörfler, axeld@xxxxxxxxxxxxxxxxx All rights 
reserved.
+ * Copyright 2012, Alex Smith, alex@xxxxxxxxxxxxxxxxx
+ * Distributed under the terms of the OpenBeOS License.
+ */
 #ifndef KERNEL_BOOT_ELF_H
 #define KERNEL_BOOT_ELF_H
 
@@ -76,15 +77,11 @@ struct preloaded_elf64_image : public preloaded_image {
        FixedWidthPointer<Elf64_Sym> debug_symbols;
 } _PACKED;
 
-#ifdef __cplusplus
-extern "C" {
-#endif
 
-extern status_t boot_elf_resolve_symbol(struct preloaded_elf32_image *image,
-       struct Elf32_Sym *symbol, addr_t *symbolAddress);
+extern status_t boot_elf_resolve_symbol(preloaded_elf32_image* image,
+       struct Elf32_Sym* symbol, Elf32_Addr* symbolAddress);
+extern status_t boot_elf_resolve_symbol(preloaded_elf64_image* image,
+       struct Elf64_Sym* symbol, Elf64_Addr* symbolAddress);
 
-#ifdef __cplusplus
-}
-#endif
 
 #endif /* KERNEL_BOOT_ELF_H */
diff --git a/headers/private/system/elf_common.h 
b/headers/private/system/elf_common.h
index 6a85bf2..61eb43f 100644
--- a/headers/private/system/elf_common.h
+++ b/headers/private/system/elf_common.h
@@ -15,14 +15,6 @@
 #include <arch_elf.h>
 
 
-typedef uint32 Elf32_Addr;
-typedef uint16 Elf32_Half;
-typedef uint32 Elf32_Off;
-typedef int32 Elf32_Sword;
-typedef uint32 Elf32_Word;
-
-typedef Elf32_Half Elf32_Versym;
-
 /*** ELF header ***/
 
 #define EI_NIDENT      16
diff --git a/src/system/boot/loader/Jamfile b/src/system/boot/loader/Jamfile
index f325c32..c948699 100644
--- a/src/system/boot/loader/Jamfile
+++ b/src/system/boot/loader/Jamfile
@@ -39,7 +39,7 @@ UsePrivateHeaders shared storage ;
                {
                        defines +=
                                ALTERNATE_BOOT_ARCH=\\\"x86_64\\\"
-                               BOOT_SUPPORT_ELF64
+                               #BOOT_SUPPORT_ELF64
 
                                BOOT_SUPPORT_PARTITION_EFI
 
@@ -50,7 +50,7 @@ UsePrivateHeaders shared storage ;
                {
                        defines +=
                                ALTERNATE_BOOT_ARCH=\\\"x86\\\"
-                               BOOT_SUPPORT_ELF64
+                               #BOOT_SUPPORT_ELF64
 
                                BOOT_SUPPORT_PARTITION_EFI
 
diff --git a/src/system/boot/loader/elf.cpp b/src/system/boot/loader/elf.cpp
index 841966b..f54e96b 100644
--- a/src/system/boot/loader/elf.cpp
+++ b/src/system/boot/loader/elf.cpp
@@ -30,233 +30,114 @@
 static bool sLoadElfSymbols = true;
 
 
-void
-elf_init()
-{
-// TODO: This cannot work, since the driver settings are loaded *after* the
-// kernel has been loaded successfully.
-#if 0
-       void *settings = load_driver_settings("kernel");
-       if (settings == NULL)
-               return;
-
-       sLoadElfSymbols = !get_driver_boolean_parameter(settings, 
"load_symbols",
-               false, false);
-       unload_driver_settings(settings);
+// #pragma mark - Generic ELF loader
+
+
+template<typename Class>
+class ELFLoader {
+private:
+       typedef typename Class::ImageType       ImageType;
+       typedef typename Class::RegionType      RegionType;
+       typedef typename Class::EhdrType        EhdrType;
+       typedef typename Class::PhdrType        PhdrType;
+       typedef typename Class::ShdrType        ShdrType;
+       typedef typename Class::DynType         DynType;
+       typedef typename Class::SymType         SymType;
+       typedef typename Class::RelType         RelType;
+       typedef typename Class::RelaType        RelaType;
+
+public:
+       static  status_t        Create(int fd, preloaded_image** _image);
+       static  status_t        Load(int fd, preloaded_image* image);
+       static  status_t        Relocate(preloaded_image* image);
+
+private:
+       static  status_t        _LoadSymbolTable(int fd, ImageType* image);
+       static  status_t        _ParseDynamicSection(ImageType* image);
+};
+
+
+struct ELF32Class {
+       static const uint8 kIdentClass = ELFCLASS32;
+
+       typedef preloaded_elf32_image   ImageType;
+       typedef elf32_region                    RegionType;
+       typedef Elf32_Ehdr                              EhdrType;
+       typedef Elf32_Phdr                              PhdrType;
+       typedef Elf32_Shdr                              ShdrType;
+       typedef Elf32_Dyn                               DynType;
+       typedef Elf32_Sym                               SymType;
+       typedef Elf32_Rel                               RelType;
+       typedef Elf32_Rela                              RelaType;
+};
+
+typedef ELFLoader<ELF32Class> ELF32Loader;
+
+
+#ifdef BOOT_SUPPORT_ELF64
+struct ELF64Class {
+       static const uint8 kIdentClass = ELFCLASS64;
+
+       typedef preloaded_elf64_image   ImageType;
+       typedef elf64_region                    RegionType;
+       typedef Elf64_Ehdr                              EhdrType;
+       typedef Elf64_Phdr                              PhdrType;
+       typedef Elf64_Shdr                              ShdrType;
+       typedef Elf64_Dyn                               DynType;
+       typedef Elf64_Sym                               SymType;
+       typedef Elf64_Rel                               RelType;
+       typedef Elf64_Rela                              RelaType;
+};
+
+typedef ELFLoader<ELF64Class> ELF64Loader;
 #endif
-}
-
-
-static status_t
-verify_elf_header(struct Elf32_Ehdr &header)
-{
-       if (memcmp(header.e_ident, ELF_MAGIC, 4) != 0
-               || header.e_ident[4] != ELFCLASS32
-               || header.e_phoff == 0
-               || !header.IsHostEndian()
-               || header.e_phentsize != sizeof(struct Elf32_Phdr))
-               return B_BAD_TYPE;
-
-       return B_OK;
-}
-
-
-static status_t
-elf_parse_dynamic_section(preloaded_elf32_image *image)
-{
-       image->syms = 0;
-       image->rel = 0;
-       image->rel_len = 0;
-       image->rela = 0;
-       image->rela_len = 0;
-       image->pltrel = 0;
-       image->pltrel_len = 0;
-       image->pltrel_type = 0;
-
-       struct Elf32_Dyn *d = (struct Elf32_Dyn *)image->dynamic_section.start;
-       if (!d)
-               return B_ERROR;
-
-       for (int i = 0; d[i].d_tag != DT_NULL; i++) {
-               switch (d[i].d_tag) {
-                       case DT_HASH:
-                       case DT_STRTAB:
-                               break;
-                       case DT_SYMTAB:
-                               image->syms = (struct Elf32_Sym 
*)(d[i].d_un.d_ptr
-                                       + image->text_region.delta);
-                               break;
-                       case DT_REL:
-                               image->rel = (struct Elf32_Rel 
*)(d[i].d_un.d_ptr
-                                       + image->text_region.delta);
-                               break;
-                       case DT_RELSZ:
-                               image->rel_len = d[i].d_un.d_val;
-                               break;
-                       case DT_RELA:
-                               image->rela = (struct Elf32_Rela 
*)(d[i].d_un.d_ptr
-                                       + image->text_region.delta);
-                               break;
-                       case DT_RELASZ:
-                               image->rela_len = d[i].d_un.d_val;
-                               break;
-                       case DT_JMPREL:
-                               image->pltrel = (struct Elf32_Rel 
*)(d[i].d_un.d_ptr
-                                       + image->text_region.delta);
-                               break;
-                       case DT_PLTRELSZ:
-                               image->pltrel_len = d[i].d_un.d_val;
-                               break;
-                       case DT_PLTREL:
-                               image->pltrel_type = d[i].d_un.d_val;
-                               break;
-
-                       default:
-                               continue;
-               }
-       }
-
-       // lets make sure we found all the required sections
-       if (image->syms == NULL)
-               return B_ERROR;
-
-       return B_OK;
-}
 
 
-static status_t
-load_elf_symbol_table(int fd, preloaded_elf32_image *image)
+template<typename Class>
+/*static*/ status_t
+ELFLoader<Class>::Create(int fd, preloaded_image** _image)
 {
-       struct Elf32_Ehdr &elfHeader = image->elf_header;
-       Elf32_Sym *symbolTable = NULL;
-       Elf32_Shdr *stringHeader = NULL;
-       uint32 numSymbols = 0;
-       char *stringTable;
-       status_t status;
-
-       // get section headers
-
-       ssize_t size = elfHeader.e_shnum * elfHeader.e_shentsize;
-       Elf32_Shdr *sectionHeaders = (struct Elf32_Shdr *)malloc(size);
-       if (sectionHeaders == NULL) {
-               dprintf("error allocating space for section headers\n");
+       ImageType* image = (ImageType*)kernel_args_malloc(sizeof(ImageType));
+       if (image == NULL)
                return B_NO_MEMORY;
-       }
-
-       ssize_t length = read_pos(fd, elfHeader.e_shoff, sectionHeaders, size);
-       if (length < size) {
-               TRACE(("error reading in program headers\n"));
-               status = B_ERROR;
-               goto error1;
-       }
-
-       // find symbol table in section headers
-
-       for (int32 i = 0; i < elfHeader.e_shnum; i++) {
-               if (sectionHeaders[i].sh_type == SHT_SYMTAB) {
-                       stringHeader = 
&sectionHeaders[sectionHeaders[i].sh_link];
-
-                       if (stringHeader->sh_type != SHT_STRTAB) {
-                               TRACE(("doesn't link to string table\n"));
-                               status = B_BAD_DATA;
-                               goto error1;
-                       }
 
-                       // read in symbol table
-                       symbolTable = (Elf32_Sym *)kernel_args_malloc(
-                               size = sectionHeaders[i].sh_size);
-                       if (symbolTable == NULL) {
-                               status = B_NO_MEMORY;
-                               goto error1;
-                       }
+       EhdrType& elfHeader = image->elf_header;
 
-                       length = read_pos(fd, sectionHeaders[i].sh_offset, 
symbolTable,
-                               size);
-                       if (length < size) {
-                               TRACE(("error reading in symbol table\n"));
-                               status = B_ERROR;
-                               goto error1;
-                       }
-
-                       numSymbols = size / sizeof(Elf32_Sym);
-                       break;
-               }
-       }
-
-       if (symbolTable == NULL) {
-               TRACE(("no symbol table\n"));
-               status = B_BAD_VALUE;
-               goto error1;
-       }
-
-       // read in string table
-
-       stringTable = (char *)kernel_args_malloc(size = stringHeader->sh_size);
-       if (stringTable == NULL) {
-               status = B_NO_MEMORY;
-               goto error2;
+       ssize_t length = read_pos(fd, 0, &elfHeader, sizeof(EhdrType));
+       if (length < (ssize_t)sizeof(EhdrType)) {
+               kernel_args_free(image);
+               return B_BAD_TYPE;
        }
 
-       length = read_pos(fd, stringHeader->sh_offset, stringTable, size);
-       if (length < size) {
-               TRACE(("error reading in string table\n"));
-               status = B_ERROR;
-               goto error3;
+       if (memcmp(elfHeader.e_ident, ELF_MAGIC, 4) != 0
+               || elfHeader.e_ident[4] != Class::kIdentClass
+               || elfHeader.e_phoff == 0
+               || !elfHeader.IsHostEndian()
+               || elfHeader.e_phentsize != sizeof(PhdrType)) {
+               kernel_args_free(image);
+               return B_BAD_TYPE;
        }
 
-       TRACE(("loaded %ld debug symbols\n", numSymbols));
-
-       // insert tables into image
-       image->debug_symbols = symbolTable;
-       image->num_debug_symbols = numSymbols;
-       image->debug_string_table = stringTable;
-       image->debug_string_table_size = size;
+       image->elf_class = elfHeader.e_ident[EI_CLASS];
 
-       free(sectionHeaders);
+       *_image = image;
        return B_OK;
-
-error3:
-       kernel_args_free(stringTable);
-error2:
-       kernel_args_free(symbolTable);
-error1:
-       free(sectionHeaders);
-
-       return status;
 }
 
 
-status_t
-elf_load_image(int fd, preloaded_image **_image)
+template<typename Class>
+/*static*/ status_t
+ELFLoader<Class>::Load(int fd, preloaded_image* _image)
 {
        size_t totalSize;
+       ssize_t length;
        status_t status;
 
-       TRACE(("elf_load_image(fd = %d, _image = %p)\n", fd, _image));
-
-       preloaded_elf32_image *image = (preloaded_elf32_image 
*)kernel_args_malloc(
-               sizeof(preloaded_elf32_image));
-       if (image == NULL)
-               return B_NO_MEMORY;
-
-       struct Elf32_Ehdr &elfHeader = image->elf_header;
-
-       ssize_t length = read_pos(fd, 0, &elfHeader, sizeof(Elf32_Ehdr));
-       if (length < (ssize_t)sizeof(Elf32_Ehdr)) {
-               kernel_args_free(image);
-               return B_BAD_TYPE;
-       }
-
-       status = verify_elf_header(elfHeader);
-       if (status < B_OK) {
-               kernel_args_free(image);
-               return status;
-       }
-
-       image->elf_class = elfHeader.e_ident[EI_CLASS];
+       ImageType* image = static_cast<ImageType*>(_image);
+       EhdrType& elfHeader = image->elf_header;
 
        ssize_t size = elfHeader.e_phnum * elfHeader.e_phentsize;
-       Elf32_Phdr *programHeaders = (struct Elf32_Phdr *)malloc(size);
+       PhdrType* programHeaders = (PhdrType*)malloc(size);
        if (programHeaders == NULL) {
                dprintf("error allocating space for program headers\n");
                status = B_NO_MEMORY;
@@ -276,7 +157,7 @@ elf_load_image(int fd, preloaded_image **_image)
        image->text_region.size = 0;
 
        for (int32 i = 0; i < elfHeader.e_phnum; i++) {
-               Elf32_Phdr &header = programHeaders[i];
+               PhdrType& header = programHeaders[i];
 
                switch (header.p_type) {
                        case PT_LOAD:
@@ -294,7 +175,7 @@ elf_load_image(int fd, preloaded_image **_image)
                                continue;
                }
 
-               elf32_region *region;
+               RegionType* region;
                if (header.IsReadWrite()) {
                        if (image->data_region.size != 0) {
                                dprintf("elf: rw already handled!\n");
@@ -327,8 +208,8 @@ elf_load_image(int fd, preloaded_image **_image)
        }
 
        // get the segment order
-       elf32_region *firstRegion;
-       elf32_region *secondRegion;
+       RegionType* firstRegion;
+       RegionType* secondRegion;
        if (image->text_region.start < image->data_region.start) {
                firstRegion = &image->text_region;
                secondRegion = &image->data_region;
@@ -363,13 +244,13 @@ elf_load_image(int fd, preloaded_image **_image)
 
        // load program data
 
-       for (int i = 0; i < elfHeader.e_phnum; i++) {
-               Elf32_Phdr &header = programHeaders[i];
+       for (int32 i = 0; i < elfHeader.e_phnum; i++) {
+               PhdrType& header = programHeaders[i];
 
                if (header.p_type != PT_LOAD)
                        continue;
 
-               elf32_region *region;
+               RegionType* region;
                if (header.IsReadWrite())
                        region = &image->data_region;
                else if (header.IsExecutable())
@@ -380,11 +261,11 @@ elf_load_image(int fd, preloaded_image **_image)
                TRACE(("load segment %d (%ld bytes)...\n", i, header.p_filesz));
 
                length = read_pos(fd, header.p_offset,
-                       (void *)(region->start + (header.p_vaddr % 
B_PAGE_SIZE)),
+                       (void*)(region->start + (header.p_vaddr % B_PAGE_SIZE)),
                        header.p_filesz);
                if (length < (ssize_t)header.p_filesz) {
                        status = B_BAD_DATA;
-                       dprintf("error reading in seg %d\n", i);
+                       dprintf("error reading in seg %ld\n", i);
                        goto error2;
                }
 
@@ -393,7 +274,7 @@ elf_load_image(int fd, preloaded_image **_image)
 
                uint32 offset = (header.p_vaddr % B_PAGE_SIZE) + 
header.p_filesz;
                if (offset < region->size)
-                       memset((void *)(region->start + offset), 0, 
region->size - offset);
+                       memset((void*)(region->start + offset), 0, region->size 
- offset);
        }
 
        // offset dynamic section, and program entry addresses by the delta of 
the
@@ -406,16 +287,15 @@ elf_load_image(int fd, preloaded_image **_image)
        image->debug_string_table = NULL;
 
        if (sLoadElfSymbols)
-               load_elf_symbol_table(fd, image);
+               _LoadSymbolTable(fd, image);
 
        free(programHeaders);
 
-       *_image = image;
        return B_OK;
 
 error2:
        if (image->text_region.start != 0)
-               platform_free_region((void *)image->text_region.start, 
totalSize);
+               platform_free_region((void*)image->text_region.start, 
totalSize);
 error1:
        free(programHeaders);
        kernel_args_free(image);
@@ -424,10 +304,270 @@ error1:
 }
 
 
+template<typename Class>
+/*static*/ status_t
+ELFLoader<Class>::Relocate(preloaded_image* _image)
+{
+       ImageType* image = static_cast<ImageType*>(_image);
+
+       status_t status = _ParseDynamicSection(image);
+       if (status != B_OK)
+               return status;
+
+       // deal with the rels first
+       if (image->rel) {
+               TRACE(("total %i relocs\n", image->rel_len / 
(int)sizeof(RelType)));
+
+               status = boot_arch_elf_relocate_rel(image, image->rel, 
image->rel_len);
+               if (status < B_OK)
+                       return status;
+       }
+
+       if (image->pltrel) {
+               TRACE(("total %i plt-relocs\n",
+                       image->pltrel_len / (int)sizeof(RelType)));
+
+               RelType* pltrel = image->pltrel;
+               if (image->pltrel_type == DT_REL) {
+                       status = boot_arch_elf_relocate_rel(image, pltrel,
+                               image->pltrel_len);
+               } else {
+                       status = boot_arch_elf_relocate_rela(image, (RelaType 
*)pltrel,
+                               image->pltrel_len);
+               }
+               if (status < B_OK)
+                       return status;
+       }
+
+       if (image->rela) {
+               TRACE(("total %i rela relocs\n",
+                       image->rela_len / (int)sizeof(RelaType)));
+               status = boot_arch_elf_relocate_rela(image, image->rela,
+                       image->rela_len);
+               if (status < B_OK)
+                       return status;
+       }
+
+       return B_OK;
+}
+
+
+template<typename Class>
+/*static*/ status_t
+ELFLoader<Class>::_LoadSymbolTable(int fd, ImageType* image)
+{
+       EhdrType& elfHeader = image->elf_header;
+       SymType* symbolTable = NULL;
+       ShdrType* stringHeader = NULL;
+       uint32 numSymbols = 0;
+       char* stringTable;
+       status_t status;
+
+       // get section headers
+
+       ssize_t size = elfHeader.e_shnum * elfHeader.e_shentsize;
+       ShdrType* sectionHeaders = (ShdrType*)malloc(size);
+       if (sectionHeaders == NULL) {
+               dprintf("error allocating space for section headers\n");
+               return B_NO_MEMORY;
+       }
+
+       ssize_t length = read_pos(fd, elfHeader.e_shoff, sectionHeaders, size);
+       if (length < size) {
+               TRACE(("error reading in program headers\n"));
+               status = B_ERROR;
+               goto error1;
+       }
+
+       // find symbol table in section headers
+
+       for (int32 i = 0; i < elfHeader.e_shnum; i++) {
+               if (sectionHeaders[i].sh_type == SHT_SYMTAB) {
+                       stringHeader = 
&sectionHeaders[sectionHeaders[i].sh_link];
+
+                       if (stringHeader->sh_type != SHT_STRTAB) {
+                               TRACE(("doesn't link to string table\n"));
+                               status = B_BAD_DATA;
+                               goto error1;
+                       }
+
+                       // read in symbol table
+                       size = sectionHeaders[i].sh_size;
+                       symbolTable = (SymType*)kernel_args_malloc(size);
+                       if (symbolTable == NULL) {
+                               status = B_NO_MEMORY;
+                               goto error1;
+                       }
+
+                       length = read_pos(fd, sectionHeaders[i].sh_offset, 
symbolTable,
+                               size);
+                       if (length < size) {
+                               TRACE(("error reading in symbol table\n"));
+                               status = B_ERROR;
+                               goto error1;
+                       }
+
+                       numSymbols = size / sizeof(SymType);
+                       break;
+               }
+       }
+
+       if (symbolTable == NULL) {
+               TRACE(("no symbol table\n"));
+               status = B_BAD_VALUE;
+               goto error1;
+       }
+
+       // read in string table
+
+       size = stringHeader->sh_size;
+       stringTable = (char*)kernel_args_malloc(size);
+       if (stringTable == NULL) {
+               status = B_NO_MEMORY;
+               goto error2;
+       }
+
+       length = read_pos(fd, stringHeader->sh_offset, stringTable, size);
+       if (length < size) {
+               TRACE(("error reading in string table\n"));
+               status = B_ERROR;
+               goto error3;
+       }
+
+       TRACE(("loaded %ld debug symbols\n", numSymbols));
+
+       // insert tables into image
+       image->debug_symbols = symbolTable;
+       image->num_debug_symbols = numSymbols;
+       image->debug_string_table = stringTable;
+       image->debug_string_table_size = size;
+
+       free(sectionHeaders);
+       return B_OK;
+
+error3:
+       kernel_args_free(stringTable);
+error2:
+       kernel_args_free(symbolTable);
+error1:
+       free(sectionHeaders);
+
+       return status;
+}
+
+
+template<typename Class>
+/*static*/ status_t
+ELFLoader<Class>::_ParseDynamicSection(ImageType* image)
+{
+       image->syms = 0;
+       image->rel = 0;
+       image->rel_len = 0;
+       image->rela = 0;
+       image->rela_len = 0;
+       image->pltrel = 0;
+       image->pltrel_len = 0;
+       image->pltrel_type = 0;
+
+       DynType* d = (DynType*)image->dynamic_section.start;
+       if (!d)
+               return B_ERROR;
+
+       for (int i = 0; d[i].d_tag != DT_NULL; i++) {
+               switch (d[i].d_tag) {
+                       case DT_HASH:
+                       case DT_STRTAB:
+                               break;
+                       case DT_SYMTAB:
+                               image->syms = (SymType*)(d[i].d_un.d_ptr
+                                       + image->text_region.delta);
+                               break;
+                       case DT_REL:
+                               image->rel = (RelType*)(d[i].d_un.d_ptr
+                                       + image->text_region.delta);
+                               break;
+                       case DT_RELSZ:
+                               image->rel_len = d[i].d_un.d_val;
+                               break;
+                       case DT_RELA:
+                               image->rela = (RelaType*)(d[i].d_un.d_ptr
+                                       + image->text_region.delta);
+                               break;
+                       case DT_RELASZ:
+                               image->rela_len = d[i].d_un.d_val;
+                               break;
+                       case DT_JMPREL:
+                               image->pltrel = (RelType*)(d[i].d_un.d_ptr
+                                       + image->text_region.delta);
+                               break;
+                       case DT_PLTRELSZ:
+                               image->pltrel_len = d[i].d_un.d_val;
+                               break;
+                       case DT_PLTREL:
+                               image->pltrel_type = d[i].d_un.d_val;
+                               break;
+
+                       default:
+                               continue;
+               }
+       }
+
+       // lets make sure we found all the required sections
+       if (image->syms == NULL)
+               return B_ERROR;
+
+       return B_OK;
+}
+
+
+// #pragma mark -
+
+
+void
+elf_init()
+{
+// TODO: This cannot work, since the driver settings are loaded *after* the
+// kernel has been loaded successfully.
+#if 0
+       void *settings = load_driver_settings("kernel");
+       if (settings == NULL)
+               return;
+
+       sLoadElfSymbols = !get_driver_boolean_parameter(settings, 
"load_symbols",
+               false, false);
+       unload_driver_settings(settings);
+#endif
+}
+
+
 status_t
-elf_load_image(Directory *directory, const char *path)
+elf_load_image(int fd, preloaded_image** _image)
 {
-       preloaded_image *image;
+       status_t status;
+
+       TRACE(("elf_load_image(fd = %d, _image = %p)\n", fd, _image));
+
+#if BOOT_SUPPORT_ELF64
+       status = ELF64Loader::Create(fd, _image);
+       if (status == B_OK) {
+               return ELF64Loader::Load(fd, *_image);
+       } else if (status == B_BAD_TYPE) {
+#endif
+               status = ELF32Loader::Create(fd, _image);
+               if (status == B_OK)
+                       return ELF32Loader::Load(fd, *_image);
+#if BOOT_SUPPORT_ELF64
+       }
+#endif
+
+       return status;
+}
+
+
+status_t
+elf_load_image(Directory* directory, const char* path)
+{
+       preloaded_image* image;
 
        TRACE(("elf_load_image(directory = %p, \"%s\")\n", directory, path));
 
@@ -469,56 +609,20 @@ elf_load_image(Directory *directory, const char *path)
 
 
 status_t
-elf_relocate_image(preloaded_image *_image)
+elf_relocate_image(preloaded_image* image)
 {
-       preloaded_elf32_image *image = static_cast<preloaded_elf32_image 
*>(_image);
-
-       status_t status = elf_parse_dynamic_section(image);
-       if (status != B_OK)
-               return status;
-
-       // deal with the rels first
-       if (image->rel) {
-               TRACE(("total %i relocs\n",
-                       image->rel_len / (int)sizeof(struct Elf32_Rel)));
-
-               status = boot_arch_elf_relocate_rel(image, image->rel, 
image->rel_len);
-               if (status < B_OK)
-                       return status;
-       }
-
-       if (image->pltrel) {
-               TRACE(("total %i plt-relocs\n",
-                       image->pltrel_len / (int)sizeof(struct Elf32_Rel)));
-
-               struct Elf32_Rel *pltrel = image->pltrel;
-               if (image->pltrel_type == DT_REL) {
-                       status = boot_arch_elf_relocate_rel(image, pltrel,
-                               image->pltrel_len);
-               } else {
-                       status = boot_arch_elf_relocate_rela(image,
-                               (struct Elf32_Rela *)pltrel, image->pltrel_len);
-               }
-               if (status < B_OK)
-                       return status;
-       }
-
-       if (image->rela) {
-               TRACE(("total %i rela relocs\n",
-                       image->rela_len / (int)sizeof(struct Elf32_Rela)));
-               status = boot_arch_elf_relocate_rela(image, image->rela,
-                       image->rela_len);
-               if (status < B_OK)
-                       return status;
-       }
-
-       return B_OK;
+#ifdef BOOT_SUPPORT_ELF64
+       if (image->elf_class == ELFCLASS64)
+               return ELF64Loader::Relocate(image);
+       else
+#endif
+               return ELF32Loader::Relocate(image);
 }
 
 
-status_t
-boot_elf_resolve_symbol(struct preloaded_elf32_image *image,
-       struct Elf32_Sym *symbol, addr_t *symbolAddress)
+template<typename ImageType, typename SymType, typename AddrType>
+inline status_t
+resolve_symbol(ImageType* image, SymType* symbol, AddrType* symbolAddress)
 {
        switch (symbol->st_shndx) {
                case SHN_UNDEF:
@@ -538,3 +642,21 @@ boot_elf_resolve_symbol(struct preloaded_elf32_image 
*image,
                        return B_NO_ERROR;
        }
 }
+
+
+status_t
+boot_elf_resolve_symbol(preloaded_elf32_image* image, struct Elf32_Sym* symbol,
+       Elf32_Addr* symbolAddress)
+{
+       return resolve_symbol(image, symbol, symbolAddress);
+}
+
+
+#ifdef BOOT_SUPPORT_ELF64
+status_t
+boot_elf_resolve_symbol(preloaded_elf64_image* image, struct Elf64_Sym* symbol,
+       Elf64_Addr* symbolAddress)
+{
+       return resolve_symbol(image, symbol, symbolAddress);
+}
+#endif
diff --git a/src/system/boot/loader/elf.h b/src/system/boot/loader/elf.h
index 9f5358a..9a0e610 100644
--- a/src/system/boot/loader/elf.h
+++ b/src/system/boot/loader/elf.h
@@ -11,9 +11,10 @@
 
 
 extern void elf_init();
-extern status_t elf_load_image(Directory *directory, const char *path);
-extern status_t elf_load_image(int fd, preloaded_image **_image);
+extern status_t elf_load_image(Directory* directory, const char* path);
+extern status_t elf_load_image(int fd, preloaded_image** _image);
+
+extern status_t elf_relocate_image(preloaded_image* image);
 
-extern status_t elf_relocate_image(preloaded_image *image);
 
 #endif /* LOADER_ELF_H */


Other related posts: