ELFLoader should fail with an error message for unresolved symbols.

This commit is contained in:
Andreas Kling 2018-10-25 10:00:37 +02:00
parent ec1d16b307
commit 16f318408d
14 changed files with 80 additions and 24 deletions

View file

@ -1,7 +1,7 @@
#pragma once #pragma once
#ifdef SERENITY #ifdef SERENITY
#include "kassert.h" #include <Kernel/kassert.h>
#else #else
#include <assert.h> #include <assert.h>
#define ASSERT(x) assert(x) #define ASSERT(x) assert(x)

9
AK/Compiler.h Normal file
View file

@ -0,0 +1,9 @@
#pragma once
#define PACKED __attribute__ ((packed))
#define NORETURN __attribute__ ((noreturn))
#define ALWAYS_INLINE __attribute__ ((always_inline))
#define NEVER_INLINE __attribute__ ((noinline))
#define MALLOC_ATTR __attribute__ ((malloc))
#define PURE __attribute__ ((pure))

View file

@ -1,5 +1,6 @@
#pragma once #pragma once
#include "Compiler.h"
#include "Types.h" #include "Types.h"
namespace AK { namespace AK {

View file

@ -1,10 +1,20 @@
#include <cstdio>
#include "SimpleMalloc.h"
#include "kmalloc.h" #include "kmalloc.h"
#ifndef SERENITY
#include <cstdio>
#include <cstdlib> #include <cstdlib>
#endif
#if defined(SERENITY) && defined(USERLAND)
#define USE_SYSTEM_MALLOC
#endif
#define USE_SYSTEM_MALLOC #define USE_SYSTEM_MALLOC
#ifndef USE_SYSTEM_MALLOC
#include "SimpleMalloc.h"
#endif
#ifdef USE_SYSTEM_MALLOC #ifdef USE_SYSTEM_MALLOC
extern "C" { extern "C" {

View file

@ -1,7 +1,11 @@
#pragma once #pragma once
#ifdef SERENITY #ifdef SERENITY
#ifdef USERLAND
#include <LibC/stdlib.h>
#else
#include <Kernel/kmalloc.h> #include <Kernel/kmalloc.h>
#endif
#else #else
#include <new> #include <new>
@ -10,7 +14,7 @@
extern "C" { extern "C" {
void* kcalloc(size_t nmemb, size_t size); void* kcalloc(size_t nmemb, size_t size);
void* kmalloc(size_t size) __attribute__ ((malloc)); void* kmalloc(size_t size) MALLOC_ATTR;
void kfree(void* ptr); void kfree(void* ptr);
void* krealloc(void* ptr, size_t size); void* krealloc(void* ptr, size_t size);

View file

@ -147,22 +147,28 @@ inline void ELFImage::forEachSectionOfType(unsigned type, F func) const
{ {
for (unsigned i = 0; i < sectionCount(); ++i) { for (unsigned i = 0; i < sectionCount(); ++i) {
auto& section = this->section(i); auto& section = this->section(i);
if (section.type() == type) if (section.type() == type) {
func(section); if (!func(section))
break;
}
} }
} }
template<typename F> template<typename F>
inline void ELFImage::RelocationSection::forEachRelocation(F func) const inline void ELFImage::RelocationSection::forEachRelocation(F func) const
{ {
for (unsigned i = 0; i < relocationCount(); ++i) for (unsigned i = 0; i < relocationCount(); ++i) {
func(relocation(i)); if (!func(relocation(i)))
break;
}
} }
template<typename F> template<typename F>
inline void ELFImage::forEachSymbol(F func) const inline void ELFImage::forEachSymbol(F func) const
{ {
for (unsigned i = 0; i < symbolCount(); ++i) for (unsigned i = 0; i < symbolCount(); ++i) {
func(symbol(i)); if (!func(symbol(i)))
break;
}
} }

View file

@ -25,26 +25,38 @@ bool ELFLoader::load()
if (!m_image->isValid()) if (!m_image->isValid())
return false; return false;
layout(); if (!layout())
return false;
exportSymbols(); exportSymbols();
performRelocations(); if (!performRelocations())
return false;
return true; return true;
} }
void ELFLoader::layout() bool ELFLoader::layout()
{ {
#ifdef ELFLOADER_DEBUG #ifdef ELFLOADER_DEBUG
kprintf("[ELFLoader] Layout\n"); kprintf("[ELFLoader] Layout\n");
#endif #endif
m_image->forEachSectionOfType(SHT_PROGBITS, [this] (const ELFImage::Section& section) { bool failed = false;
m_image->forEachSectionOfType(SHT_PROGBITS, [this, &failed] (const ELFImage::Section& section) {
#ifdef ELFLOADER_DEBUG #ifdef ELFLOADER_DEBUG
kprintf("[ELFLoader] Allocating progbits section: %s\n", section.name()); kprintf("[ELFLoader] Allocating progbits section: %s\n", section.name());
#endif #endif
if (!section.size())
return true;
char* ptr = m_execSpace.allocateArea(section.name(), section.size()); char* ptr = m_execSpace.allocateArea(section.name(), section.size());
if (!ptr) {
kprintf("ELFLoader: failed to allocate section '%s'\n", section.name());
failed = true;
return false;
}
memcpy(ptr, section.rawData(), section.size()); memcpy(ptr, section.rawData(), section.size());
m_sections.set(section.name(), move(ptr)); m_sections.set(section.name(), move(ptr));
return true;
}); });
return !failed;
} }
void* ELFLoader::lookup(const ELFImage::Symbol& symbol) void* ELFLoader::lookup(const ELFImage::Symbol& symbol)
@ -67,23 +79,30 @@ char* ELFLoader::areaForSectionName(const char* name)
return nullptr; return nullptr;
} }
void ELFLoader::performRelocations() bool ELFLoader::performRelocations()
{ {
#ifdef ELFLOADER_DEBUG #ifdef ELFLOADER_DEBUG
kprintf("[ELFLoader] Performing relocations\n"); kprintf("[ELFLoader] Performing relocations\n");
#endif #endif
m_image->forEachSectionOfType(SHT_PROGBITS, [this] (const ELFImage::Section& section) { bool failed = false;
m_image->forEachSectionOfType(SHT_PROGBITS, [this, &failed] (const ELFImage::Section& section) -> bool {
auto& relocations = section.relocations(); auto& relocations = section.relocations();
if (relocations.isUndefined()) if (relocations.isUndefined())
return; return true;
relocations.forEachRelocation([this, section] (const ELFImage::Relocation& relocation) { relocations.forEachRelocation([this, section, &failed] (const ELFImage::Relocation& relocation) {
auto symbol = relocation.symbol(); auto symbol = relocation.symbol();
auto& patchPtr = *reinterpret_cast<ptrdiff_t*>(areaForSection(section) + relocation.offset()); auto& patchPtr = *reinterpret_cast<ptrdiff_t*>(areaForSection(section) + relocation.offset());
switch (relocation.type()) { switch (relocation.type()) {
case R_386_PC32: { case R_386_PC32: {
char* targetPtr = (char*)lookup(symbol); char* targetPtr = (char*)lookup(symbol);
if (!targetPtr) {
kprintf("ELFLoader: unresolved symbol '%s'\n", symbol.name());
failed = true;
return false;
}
ptrdiff_t relativeOffset = (char*)targetPtr - ((char*)&patchPtr + 4); ptrdiff_t relativeOffset = (char*)targetPtr - ((char*)&patchPtr + 4);
#ifdef ELFLOADER_DEBUG #ifdef ELFLOADER_DEBUG
kprintf("[ELFLoader] Relocate PC32: offset=%x, symbol=%u(%s) value=%x target=%p, offset=%d\n", kprintf("[ELFLoader] Relocate PC32: offset=%x, symbol=%u(%s) value=%x target=%p, offset=%d\n",
@ -115,8 +134,11 @@ void ELFLoader::performRelocations()
ASSERT_NOT_REACHED(); ASSERT_NOT_REACHED();
break; break;
} }
return true;
}); });
return !failed;
}); });
return !failed;
} }
void ELFLoader::exportSymbols() void ELFLoader::exportSymbols()
@ -128,6 +150,7 @@ void ELFLoader::exportSymbols()
if (symbol.type() == STT_FUNC) if (symbol.type() == STT_FUNC)
m_execSpace.addSymbol(symbol.name(), areaForSection(symbol.section()) + symbol.value(), symbol.size()); m_execSpace.addSymbol(symbol.name(), areaForSection(symbol.section()) + symbol.value(), symbol.size());
// FIXME: What about other symbol types? // FIXME: What about other symbol types?
return true;
}); });
} }

View file

@ -19,8 +19,8 @@ public:
bool load(); bool load();
private: private:
void layout(); bool layout();
void performRelocations(); bool performRelocations();
void exportSymbols(); void exportSymbols();
void* lookup(const ELFImage::Symbol&); void* lookup(const ELFImage::Symbol&);
char* areaForSection(const ELFImage::Section&); char* areaForSection(const ELFImage::Section&);

View file

@ -201,6 +201,7 @@ Task* Task::create(const String& path, uid_t uid, gid_t gid, pid_t parentPID)
bool success = space.loadELF(move(elfData)); bool success = space.loadELF(move(elfData));
if (!success) { if (!success) {
delete t; delete t;
kprintf("Failure loading ELF %s\n", path.characters());
return nullptr; return nullptr;
} }

Binary file not shown.

View file

@ -1,5 +1,7 @@
#pragma once #pragma once
#include <AK/Compiler.h>
int kprintf(const char *fmt, ...); int kprintf(const char *fmt, ...);
int ksprintf(char* buf, const char *fmt, ...); int ksprintf(char* buf, const char *fmt, ...);

View file

@ -12,7 +12,7 @@ typedef signed char signed_byte;
typedef dword uid_t; typedef dword uid_t;
typedef dword gid_t; typedef dword gid_t;
typedef dword pid_t; typedef int pid_t;
typedef dword size_t; typedef dword size_t;
typedef signed_dword ssize_t; typedef signed_dword ssize_t;

View file

@ -9,12 +9,12 @@ uid_t getuid()
return Syscall::invoke(Syscall::PosixGetuid); return Syscall::invoke(Syscall::PosixGetuid);
} }
uid_t getgid() gid_t getgid()
{ {
return Syscall::invoke(Syscall::PosixGetgid); return Syscall::invoke(Syscall::PosixGetgid);
} }
uid_t getpid() pid_t getpid()
{ {
return Syscall::invoke(Syscall::PosixGetpid); return Syscall::invoke(Syscall::PosixGetpid);
} }

View file

@ -20,7 +20,7 @@ FLAVOR_FLAGS = -fomit-frame-pointer -mregparm=3 -march=i386 -m32 -fno-exceptions
OPTIMIZATION_FLAGS = -Os -fno-asynchronous-unwind-tables OPTIMIZATION_FLAGS = -Os -fno-asynchronous-unwind-tables
INCLUDE_FLAGS = -I.. -I. INCLUDE_FLAGS = -I.. -I.
DEFINES = -DSERENITY -DSANITIZE_PTRS DEFINES = -DSERENITY -DSANITIZE_PTRS -DUSERLAND
CXXFLAGS = $(WARNING_FLAGS) $(OPTIMIZATION_FLAGS) $(USERLAND_FLAGS) $(FLAVOR_FLAGS) $(ARCH_FLAGS) $(STANDARD_FLAGS) $(INCLUDE_FLAGS) $(DEFINES) CXXFLAGS = $(WARNING_FLAGS) $(OPTIMIZATION_FLAGS) $(USERLAND_FLAGS) $(FLAVOR_FLAGS) $(ARCH_FLAGS) $(STANDARD_FLAGS) $(INCLUDE_FLAGS) $(DEFINES)
CXX = g++ CXX = g++