mirror of
https://github.com/SerenityOS/serenity
synced 2024-10-07 00:19:27 +00:00
ELFLoader should fail with an error message for unresolved symbols.
This commit is contained in:
parent
ec1d16b307
commit
16f318408d
|
@ -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
9
AK/Compiler.h
Normal 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))
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include "Compiler.h"
|
||||||
#include "Types.h"
|
#include "Types.h"
|
||||||
|
|
||||||
namespace AK {
|
namespace AK {
|
||||||
|
|
|
@ -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" {
|
||||||
|
|
|
@ -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);
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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&);
|
||||||
|
|
|
@ -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.
|
@ -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, ...);
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
|
@ -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++
|
||||||
|
|
Loading…
Reference in a new issue