kernel: support elf32 on x86_64.

* define ELF32_COMPAT to enable ELF32 macros.
* add a flag ELF_LOAD_USER_IMAGE_TEST_EXECUTABLE to only check the format.
It will be used by load_image_internal() to check which mode to use when
loading an image.
* in arch_elf_relocate_rel(), switch to elf_addr instead of addr_t, which
would be the wrong size for elf32 on x86_64.
* the ELF compat loader reuses the relevant parts of elf.cpp and arch_elf.cpp,
excluding for instance load_kernel_add_on() or dump functions.

Change-Id: Ifa47334e5adefd45405a823a3accbd12eee5b116
This commit is contained in:
Jérôme Duval 2018-05-04 21:06:23 +02:00
parent 496080235a
commit a553e95d85
8 changed files with 111 additions and 27 deletions

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2005, Haiku Inc. All Rights Reserved. * Copyright 2005-2018 Haiku Inc. All Rights Reserved.
* Distributed under the terms of the MIT license. * Distributed under the terms of the MIT license.
* *
* Copyright 2001-2002, Travis Geiselbrecht. All rights reserved. * Copyright 2001-2002, Travis Geiselbrecht. All rights reserved.
@ -27,8 +27,13 @@ struct elf_symbol_info {
extern "C" { extern "C" {
#endif #endif
status_t elf_load_user_image(const char *path, Team *team, int flags, status_t elf_load_user_image(const char *path, Team *team, uint32 flags,
addr_t *_entry); addr_t *_entry);
#ifdef _COMPAT_MODE
#define ELF_LOAD_USER_IMAGE_TEST_EXECUTABLE 0x1
status_t elf32_load_user_image(const char *path, Team *team, uint32 flags,
addr_t *_entry);
#endif
// these two might get public one day: // these two might get public one day:
image_id load_kernel_add_on(const char *path); image_id load_kernel_add_on(const char *path);

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2002-2007, Haiku Inc. All Rights Reserved. * Copyright 2002-2018, Haiku Inc. All Rights Reserved.
* Distributed under the terms of the MIT license. * Distributed under the terms of the MIT license.
* *
* Copyright 2001-2002, Travis Geiselbrecht. All rights reserved. * Copyright 2001-2002, Travis Geiselbrecht. All rights reserved.
@ -81,7 +81,7 @@ extern "C" {
extern status_t elf_resolve_symbol(struct elf_image_info* image, extern status_t elf_resolve_symbol(struct elf_image_info* image,
elf_sym* symbol, struct elf_image_info* sharedImage, elf_sym* symbol, struct elf_image_info* sharedImage,
addr_t* _symbolAddress); elf_addr* _symbolAddress);
#ifdef __cplusplus #ifdef __cplusplus
} }

View File

@ -47,7 +47,7 @@
#define R_X86_64_IRELATIVE 37 /* Adjust indirectly by program base. */ #define R_X86_64_IRELATIVE 37 /* Adjust indirectly by program base. */
#ifdef _BOOT_MODE #if defined(_BOOT_MODE) || defined(ELF32_COMPAT)
# include "../x86/arch_elf.h" # include "../x86/arch_elf.h"
#endif #endif

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2002-2016 Haiku, Inc. All rights reserved. * Copyright 2002-2018 Haiku, Inc. All rights reserved.
* Distributed under the terms of the MIT License. * Distributed under the terms of the MIT License.
* *
* Copyright 2001 Travis Geiselbrecht. All rights reserved. * Copyright 2001 Travis Geiselbrecht. All rights reserved.
@ -18,7 +18,7 @@
// Determine the correct ELF types to use for the architecture // Determine the correct ELF types to use for the architecture
#if B_HAIKU_64_BIT #if defined(B_HAIKU_64_BIT) && !defined(ELF32_COMPAT)
# define _ELF_TYPE(type) Elf64_##type # define _ELF_TYPE(type) Elf64_##type
#else #else
# define _ELF_TYPE(type) Elf32_##type # define _ELF_TYPE(type) Elf32_##type
@ -26,6 +26,7 @@
#define DEFINE_ELF_TYPE(type, name) \ #define DEFINE_ELF_TYPE(type, name) \
typedef _ELF_TYPE(type) name typedef _ELF_TYPE(type) name
DEFINE_ELF_TYPE(Addr, elf_addr);
DEFINE_ELF_TYPE(Ehdr, elf_ehdr); DEFINE_ELF_TYPE(Ehdr, elf_ehdr);
DEFINE_ELF_TYPE(Phdr, elf_phdr); DEFINE_ELF_TYPE(Phdr, elf_phdr);
DEFINE_ELF_TYPE(Shdr, elf_shdr); DEFINE_ELF_TYPE(Shdr, elf_shdr);
@ -48,7 +49,7 @@ DEFINE_ELF_TYPE(Note_Thread_Entry, elf_note_thread_entry);
typedef uint16 elf_versym; typedef uint16 elf_versym;
#if B_HAIKU_64_BIT #if defined(B_HAIKU_64_BIT) && !defined(ELF32_COMPAT)
# define ELF_CLASS ELFCLASS64 # define ELF_CLASS ELFCLASS64
#else #else
# define ELF_CLASS ELFCLASS32 # define ELF_CLASS ELFCLASS32

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2004-2008, Haiku Inc. All Rights Reserved. * Copyright 2004-2018, Haiku Inc. All Rights Reserved.
* Distributed under the terms of the MIT license. * Distributed under the terms of the MIT license.
* *
* Copyright 2002, Travis Geiselbrecht. All rights reserved. * Copyright 2002, Travis Geiselbrecht. All rights reserved.
@ -37,7 +37,8 @@ is_in_image(struct elf_image_info *image, addr_t address)
#endif // !_BOOT_MODE #endif // !_BOOT_MODE
#if !defined(__x86_64__) || (defined(_BOOT_MODE) && _BOOT_PLATFORM != efi) #if !defined(__x86_64__) || defined(ELF32_COMPAT) \
|| (defined(_BOOT_MODE) && _BOOT_PLATFORM != efi)
#ifdef TRACE_ARCH_ELF #ifdef TRACE_ARCH_ELF
@ -67,11 +68,11 @@ arch_elf_relocate_rel(struct elf_image_info *image,
struct elf_image_info *resolveImage, Elf32_Rel *rel, int relLength) struct elf_image_info *resolveImage, Elf32_Rel *rel, int relLength)
#endif #endif
{ {
addr_t S; elf_addr S;
addr_t A; uint32 A;
addr_t P; uint32 P;
addr_t finalAddress; uint32 finalAddress;
addr_t *resolveAddress; uint32 *resolveAddress;
int i; int i;
S = A = P = 0; S = A = P = 0;
@ -112,7 +113,7 @@ arch_elf_relocate_rel(struct elf_image_info *image,
case R_386_RELATIVE: case R_386_RELATIVE:
case R_386_GOTOFF: case R_386_GOTOFF:
case R_386_GOTPC: case R_386_GOTPC:
A = *(addr_t *)(image->text_region.delta + rel[i].r_offset); A = *(uint32 *)(image->text_region.delta + rel[i].r_offset);
TRACE(("A %p\n", (void *)A)); TRACE(("A %p\n", (void *)A));
break; break;
} }
@ -151,7 +152,7 @@ arch_elf_relocate_rel(struct elf_image_info *image,
return B_BAD_DATA; return B_BAD_DATA;
} }
resolveAddress = (addr_t *)(image->text_region.delta + rel[i].r_offset); resolveAddress = (uint32 *)(image->text_region.delta + rel[i].r_offset);
#ifndef _BOOT_MODE #ifndef _BOOT_MODE
if (!is_in_image(image, (addr_t)resolveAddress)) { if (!is_in_image(image, (addr_t)resolveAddress)) {
dprintf("arch_elf_relocate_rel: invalid offset %#lx\n", dprintf("arch_elf_relocate_rel: invalid offset %#lx\n",
@ -160,8 +161,8 @@ arch_elf_relocate_rel(struct elf_image_info *image,
} }
#endif #endif
*resolveAddress = finalAddress; *resolveAddress = finalAddress;
TRACE(("-> offset %#lx = %#lx\n", TRACE(("-> offset %#lx (%#lx) = %#lx\n",
(image->text_region.delta + rel[i].r_offset), finalAddress)); (image->text_region.delta + rel[i].r_offset), rel[i].r_offset, finalAddress));
} }
return B_NO_ERROR; return B_NO_ERROR;
@ -183,10 +184,10 @@ arch_elf_relocate_rela(struct elf_image_info *image,
} }
#endif // !__x86_64__ || (_BOOT_MODE && _BOOT_PLATFORM != efi) #endif // !__x86_64__ || defined(ELF32_COMPAT) || (_BOOT_MODE && _BOOT_PLATFORM != efi)
#if defined(__x86_64__) || defined(_BOOT_MODE) #if (defined(__x86_64__) && !defined(ELF32_COMPAT)) || defined(_BOOT_MODE)
#ifdef _BOOT_MODE #ifdef _BOOT_MODE
@ -276,4 +277,4 @@ arch_elf_relocate_rela(struct elf_image_info *image,
} }
#endif // __x86_64__ || _BOOT_MODE #endif // (defined(__x86_64__) && !defined(ELF32_COMPAT)) || defined(_BOOT_MODE)

View File

@ -0,0 +1,18 @@
/*
* Copyright 2018, Jérôme Duval, jerome.duval@gmail.com.
* Distributed under the terms of the MIT License.
*/
/*! Contains the ELF compat loader */
//#define TRACE_ARCH_ELF
#define ELF32_COMPAT 1
#define arch_elf_relocate_rel arch_elf32_relocate_rel
#define arch_elf_relocate_rela arch_elf32_relocate_rela
#define elf_resolve_symbol elf32_resolve_symbol
#include "arch_elf.cpp"

View File

@ -83,6 +83,8 @@ typedef BOpenHashTable<ImageHashDefinition> ImageHash;
} // namespace } // namespace
#ifndef ELF32_COMPAT
static ImageHash *sImagesHash; static ImageHash *sImagesHash;
static struct elf_image_info *sKernelImage = NULL; static struct elf_image_info *sKernelImage = NULL;
@ -253,6 +255,9 @@ find_image_by_vnode(void *vnode)
} }
#endif // ELF32_COMPAT
static struct elf_image_info * static struct elf_image_info *
create_image_struct() create_image_struct()
{ {
@ -340,6 +345,9 @@ get_symbol_bind_string(elf_sym *symbol)
} }
#ifndef ELF32_COMPAT
/*! Searches a symbol (pattern) in all kernel images */ /*! Searches a symbol (pattern) in all kernel images */
static int static int
dump_symbol(int argc, char **argv) dump_symbol(int argc, char **argv)
@ -571,8 +579,7 @@ dump_image(int argc, char **argv)
// Currently unused // Currently unused
#if 0 /*static
static
void dump_symbol(struct elf_image_info *image, elf_sym *sym) void dump_symbol(struct elf_image_info *image, elf_sym *sym)
{ {
@ -585,7 +592,10 @@ void dump_symbol(struct elf_image_info *image, elf_sym *sym)
kprintf(" st_other 0x%x\n", sym->st_other); kprintf(" st_other 0x%x\n", sym->st_other);
kprintf(" st_shndx %d\n", sym->st_shndx); kprintf(" st_shndx %d\n", sym->st_shndx);
} }
#endif */
#endif // ELF32_COMPAT
static elf_sym * static elf_sym *
@ -800,6 +810,9 @@ elf_parse_dynamic_section(struct elf_image_info *image)
} }
#ifndef ELF32_COMPAT
static status_t static status_t
assert_defined_image_version(elf_image_info* dependentImage, assert_defined_image_version(elf_image_info* dependentImage,
elf_image_info* image, const elf_version_info& neededVersion, bool weak) elf_image_info* image, const elf_version_info& neededVersion, bool weak)
@ -980,12 +993,15 @@ check_needed_image_versions(elf_image_info* image)
} }
#endif // ELF32_COMPAT
/*! Resolves the \a symbol by linking against \a sharedImage if necessary. /*! Resolves the \a symbol by linking against \a sharedImage if necessary.
Returns the resolved symbol's address in \a _symbolAddress. Returns the resolved symbol's address in \a _symbolAddress.
*/ */
status_t status_t
elf_resolve_symbol(struct elf_image_info *image, elf_sym *symbol, elf_resolve_symbol(struct elf_image_info *image, elf_sym *symbol,
struct elf_image_info *sharedImage, addr_t *_symbolAddress) struct elf_image_info *sharedImage, elf_addr *_symbolAddress)
{ {
// Local symbols references are always resolved to the given symbol. // Local symbols references are always resolved to the given symbol.
if (symbol->Bind() == STB_LOCAL) { if (symbol->Bind() == STB_LOCAL) {
@ -1124,6 +1140,9 @@ verify_eheader(elf_ehdr *elfHeader)
} }
#ifndef ELF32_COMPAT
static void static void
unload_elf_image(struct elf_image_info *image) unload_elf_image(struct elf_image_info *image)
{ {
@ -1803,8 +1822,11 @@ elf_lookup_kernel_symbol(const char* name, elf_symbol_info* info)
} }
#endif // ELF32_COMPAT
status_t status_t
elf_load_user_image(const char *path, Team *team, int flags, addr_t *entry) elf_load_user_image(const char *path, Team *team, uint32 flags, addr_t *entry)
{ {
elf_ehdr elfHeader; elf_ehdr elfHeader;
elf_phdr *programHeaders = NULL; elf_phdr *programHeaders = NULL;
@ -1845,6 +1867,11 @@ elf_load_user_image(const char *path, Team *team, int flags, addr_t *entry)
if (status < B_OK) if (status < B_OK)
goto error; goto error;
#ifdef ELF_LOAD_USER_IMAGE_TEST_EXECUTABLE
if ((flags & ELF_LOAD_USER_IMAGE_TEST_EXECUTABLE) != 0)
return B_OK;
#endif
struct elf_image_info* image; struct elf_image_info* image;
image = create_image_struct(); image = create_image_struct();
if (image == NULL) { if (image == NULL) {
@ -2088,6 +2115,7 @@ elf_load_user_image(const char *path, Team *team, int flags, addr_t *entry)
status = B_OK; status = B_OK;
error2: error2:
clear_ac();
free(mappedAreas); free(mappedAreas);
image->elf_header = NULL; image->elf_header = NULL;
@ -2101,6 +2129,8 @@ error:
} }
#ifndef ELF32_COMPAT
image_id image_id
load_kernel_add_on(const char *path) load_kernel_add_on(const char *path)
{ {
@ -2750,3 +2780,6 @@ _user_read_kernel_image_symbols(image_id id, elf_sym* symbolTable,
return elf_read_kernel_image_symbols(id, symbolTable, _symbolCount, return elf_read_kernel_image_symbols(id, symbolTable, _symbolCount,
stringTable, _stringTableSize, _imageDelta, false); stringTable, _stringTableSize, _imageDelta, false);
} }
#endif // ELF32_COMPAT

View File

@ -0,0 +1,26 @@
/*
* Copyright 2018, Jérôme Duval, jerome.duval@gmail.com.
* Distributed under the terms of the MIT License.
*/
/*! Contains the ELF compat loader */
//#define TRACE_ELF
#define ELF32_COMPAT 1
#include <elf.h>
#define elf_load_user_image elf32_load_user_image
#define elf_resolve_symbol elf32_resolve_symbol
#define elf_find_symbol elf32_find_symbol
#define elf_parse_dynamic_section elf32_parse_dynamic_section
#define elf_relocate elf32_relocate
#define arch_elf_relocate_rel arch_elf32_relocate_rel
#define arch_elf_relocate_rela arch_elf32_relocate_rela
#include "elf.cpp"