diff --git a/src/system/runtime_loader/Jamfile b/src/system/runtime_loader/Jamfile index 5476f5da01..46239d120e 100644 --- a/src/system/runtime_loader/Jamfile +++ b/src/system/runtime_loader/Jamfile @@ -1,6 +1,11 @@ SubDir HAIKU_TOP src system runtime_loader ; +if $(TARGET_ARCH) = x86_64 + && ( x86 in $(HAIKU_ARCHS[2-]) || x86_gcc2 in $(HAIKU_ARCHS[2-]) ) { + DEFINES += _COMPAT_MODE ; +} + local architectureObject ; for architectureObject in [ MultiArchSubDirSetup ] { on $(architectureObject) { diff --git a/src/system/runtime_loader/arch/x86/Jamfile b/src/system/runtime_loader/arch/x86/Jamfile index 444c3211b0..68cb226dd0 100644 --- a/src/system/runtime_loader/arch/x86/Jamfile +++ b/src/system/runtime_loader/arch/x86/Jamfile @@ -16,7 +16,12 @@ for architectureObject in [ MultiArchSubDirSetup x86 x86_gcc2 ] { atomic.o thread.o - arch_string.o + [ MultiArchIfPrimary + memcpy.o + memset.o + : + arch_string.o + : x86_64 ] ; } } diff --git a/src/system/runtime_loader/elf.cpp b/src/system/runtime_loader/elf.cpp index 03b8bd1c73..018315955d 100644 --- a/src/system/runtime_loader/elf.cpp +++ b/src/system/runtime_loader/elf.cpp @@ -1012,6 +1012,33 @@ elf_verify_header(void *header, size_t length) } +#ifdef _COMPAT_MODE +#ifdef __x86_64__ +status_t +elf32_verify_header(void *header, size_t length) +{ + int32 programSize, sectionSize; + + if (length < sizeof(Elf32_Ehdr)) + return B_NOT_AN_EXECUTABLE; + + return parse_elf32_header((Elf32_Ehdr *)header, &programSize, §ionSize); +} +#else +status_t +elf64_verify_header(void *header, size_t length) +{ + int32 programSize, sectionSize; + + if (length < sizeof(Elf64_Ehdr)) + return B_NOT_AN_EXECUTABLE; + + return parse_elf64_header((Elf64_Ehdr *)header, &programSize, §ionSize); +} +#endif // __x86_64__ +#endif // _COMPAT_MODE + + void terminate_program(void) { diff --git a/src/system/runtime_loader/elf_load_image.cpp b/src/system/runtime_loader/elf_load_image.cpp index 3822f36266..ebd3f41b0f 100644 --- a/src/system/runtime_loader/elf_load_image.cpp +++ b/src/system/runtime_loader/elf_load_image.cpp @@ -421,6 +421,61 @@ parse_elf_header(elf_ehdr* eheader, int32* _pheaderSize, } +#if defined(_COMPAT_MODE) +#if defined(__x86_64__) +status_t +parse_elf32_header(Elf32_Ehdr* eheader, int32* _pheaderSize, + int32* _sheaderSize) +{ + if (memcmp(eheader->e_ident, ELFMAG, 4) != 0) + return B_NOT_AN_EXECUTABLE; + + if (eheader->e_ident[4] != ELFCLASS32) + return B_NOT_AN_EXECUTABLE; + + if (eheader->e_phoff == 0) + return B_NOT_AN_EXECUTABLE; + + if (eheader->e_phentsize < sizeof(Elf32_Phdr)) + return B_NOT_AN_EXECUTABLE; + + *_pheaderSize = eheader->e_phentsize * eheader->e_phnum; + *_sheaderSize = eheader->e_shentsize * eheader->e_shnum; + + if (*_pheaderSize <= 0 || *_sheaderSize <= 0) + return B_NOT_AN_EXECUTABLE; + + return B_OK; +} +#else +status_t +parse_elf64_header(Elf64_Ehdr* eheader, int32* _pheaderSize, + int32* _sheaderSize) +{ + if (memcmp(eheader->e_ident, ELFMAG, 4) != 0) + return B_NOT_AN_EXECUTABLE; + + if (eheader->e_ident[4] != ELFCLASS64) + return B_NOT_AN_EXECUTABLE; + + if (eheader->e_phoff == 0) + return B_NOT_AN_EXECUTABLE; + + if (eheader->e_phentsize < sizeof(Elf64_Phdr)) + return B_NOT_AN_EXECUTABLE; + + *_pheaderSize = eheader->e_phentsize * eheader->e_phnum; + *_sheaderSize = eheader->e_shentsize * eheader->e_shnum; + + if (*_pheaderSize <= 0 || *_sheaderSize <= 0) + return B_NOT_AN_EXECUTABLE; + + return B_OK; +} +#endif // __x86_64__ +#endif // _COMPAT_MODE + + status_t load_image(char const* name, image_type type, const char* rpath, const char* requestingObjectPath, image_t** _image) @@ -574,6 +629,9 @@ load_image(char const* name, image_type type, const char* rpath, // loading) we init the search path subdir if the compiler version doesn't // match ours. if (sSearchPathSubDir == NULL) { +#if defined(_COMPAT_MODE) && !defined(__x86_64__) + sSearchPathSubDir = "x86"; +#else #if __GNUC__ == 2 if ((image->abi & B_HAIKU_ABI_MAJOR) == B_HAIKU_ABI_GCC_4) sSearchPathSubDir = "x86"; @@ -581,6 +639,7 @@ load_image(char const* name, image_type type, const char* rpath, if ((image->abi & B_HAIKU_ABI_MAJOR) == B_HAIKU_ABI_GCC_2) sSearchPathSubDir = "x86_gcc2"; #endif +#endif } set_abi_version(image->abi); diff --git a/src/system/runtime_loader/elf_load_image.h b/src/system/runtime_loader/elf_load_image.h index 77ead88b86..061c0677ae 100644 --- a/src/system/runtime_loader/elf_load_image.h +++ b/src/system/runtime_loader/elf_load_image.h @@ -10,6 +10,15 @@ status_t parse_elf_header(elf_ehdr* eheader, int32* _pheaderSize, int32* _sheaderSize); +#if defined(_COMPAT_MODE) + #if defined(__x86_64__) +status_t parse_elf32_header(Elf32_Ehdr* eheader, int32* _pheaderSize, + int32* _sheaderSize); + #else +status_t parse_elf64_header(Elf64_Ehdr* eheader, int32* _pheaderSize, + int32* _sheaderSize); + #endif +#endif status_t load_image(char const* name, image_type type, const char* rpath, const char* requestingObjectPath, image_t** _image); diff --git a/src/system/runtime_loader/runtime_loader.cpp b/src/system/runtime_loader/runtime_loader.cpp index 3aa9cc34e8..e632895e92 100644 --- a/src/system/runtime_loader/runtime_loader.cpp +++ b/src/system/runtime_loader/runtime_loader.cpp @@ -416,6 +416,15 @@ test_executable(const char *name, char *invoker) } status = elf_verify_header(buffer, length); +#ifdef _COMPAT_MODE +#ifdef __x86_64__ + if (status == B_NOT_AN_EXECUTABLE) + status = elf32_verify_header(buffer, length); +#else + if (status == B_NOT_AN_EXECUTABLE) + status = elf64_verify_header(buffer, length); +#endif // __x86_64__ +#endif // _COMPAT_MODE if (status == B_NOT_AN_EXECUTABLE) { if (!strncmp(buffer, "#!", 2)) { // test for shell scripts diff --git a/src/system/runtime_loader/runtime_loader_private.h b/src/system/runtime_loader/runtime_loader_private.h index be40233378..5df7dc6b7a 100644 --- a/src/system/runtime_loader/runtime_loader_private.h +++ b/src/system/runtime_loader/runtime_loader_private.h @@ -30,12 +30,17 @@ # define KTRACE(x...) #endif // RUNTIME_LOADER_TRACING - +#if defined(_COMPAT_MODE) && !defined(__x86_64__) +#define RLD_PREFIX "runtime_loader_compat: " +#endif +#ifndef RLD_PREFIX +#define RLD_PREFIX "runtime_loader: " +#endif #define FATAL(x...) \ do { \ - dprintf("runtime_loader: " x); \ + dprintf(RLD_PREFIX x); \ if (!gProgramLoaded) \ - printf("runtime_loader: " x); \ + printf(RLD_PREFIX x); \ } while (false) @@ -81,6 +86,13 @@ int resolve_symbol(image_t* rootImage, image_t* image, elf_sym* sym, status_t elf_verify_header(void* header, size_t length); +#ifdef _COMPAT_MODE +#ifdef __x86_64__ +status_t elf32_verify_header(void *header, size_t length); +#else +status_t elf64_verify_header(void *header, size_t length); +#endif // __x86_64__ +#endif // _COMPAT_MODE void rldelf_init(void); void rldexport_init(void); void set_abi_version(int abi_version);