Simple ELF program loader
Now any initrd file is treated like a program image and passed to the loader to load as a process. Very rudimentary elf loading just allocates pages, copies sections, and sets the ELF's entrypoint as the RIP to iretq to.
This commit is contained in:
49
src/libraries/elf/elf.cpp
Normal file
49
src/libraries/elf/elf.cpp
Normal file
@@ -0,0 +1,49 @@
|
||||
#include "elf/elf.h"
|
||||
#include "elf/headers.h"
|
||||
|
||||
static const uint32_t expected_magic = 0x464c457f; // "\x7f" "ELF"
|
||||
|
||||
namespace elf {
|
||||
|
||||
elf::elf(const void *data, size_t size) :
|
||||
m_data(data),
|
||||
m_size(size)
|
||||
{
|
||||
}
|
||||
|
||||
bool
|
||||
elf::valid() const
|
||||
{
|
||||
const file_header *fheader = header();
|
||||
|
||||
return
|
||||
fheader->magic == expected_magic &&
|
||||
fheader->word_size == wordsize::bits64 &&
|
||||
fheader->endianness == encoding::lsb &&
|
||||
fheader->os_abi == osabi::sysV &&
|
||||
fheader->file_type == filetype::executable &&
|
||||
fheader->machine_type == machine::x64 &&
|
||||
fheader->ident_version == 1 &&
|
||||
fheader->version == 1;
|
||||
}
|
||||
|
||||
const program_header *
|
||||
elf::program(unsigned index) const
|
||||
{
|
||||
const file_header *fheader = header();
|
||||
uint64_t off = fheader->ph_offset + (index * fheader->ph_entsize);
|
||||
const void *pheader = kutil::offset_pointer(m_data, off);
|
||||
return reinterpret_cast<const program_header *>(pheader);
|
||||
}
|
||||
|
||||
const section_header *
|
||||
elf::section(unsigned index) const
|
||||
{
|
||||
const file_header *fheader = header();
|
||||
uint64_t off = fheader->sh_offset + (index * fheader->sh_entsize);
|
||||
const void *sheader = kutil::offset_pointer(m_data, off);
|
||||
return reinterpret_cast<const section_header *>(sheader);
|
||||
}
|
||||
|
||||
|
||||
} // namespace elf
|
||||
61
src/libraries/elf/elf.h
Normal file
61
src/libraries/elf/elf.h
Normal file
@@ -0,0 +1,61 @@
|
||||
#pragma once
|
||||
#include <stddef.h>
|
||||
#include "elf/headers.h"
|
||||
#include "kutil/memory.h"
|
||||
|
||||
namespace elf {
|
||||
|
||||
class elf
|
||||
{
|
||||
public:
|
||||
/// Constructor: Create an elf object out of ELF data in memory
|
||||
/// \arg data The ELF data to read
|
||||
/// \arg size Size of the ELF data, in bytes
|
||||
elf(const void *data, size_t size);
|
||||
|
||||
/// Check the validity of the ELF data
|
||||
/// \returns true for valid ELF data
|
||||
bool valid() const;
|
||||
|
||||
/// Get the entrypoint address of the program image
|
||||
/// \returns A pointer to the entrypoint of the program
|
||||
inline addr_t entrypoint() const
|
||||
{
|
||||
return static_cast<addr_t>(header()->entrypoint);
|
||||
}
|
||||
|
||||
/// Get the number of program sections in the image
|
||||
/// \returns The number of program section entries
|
||||
inline unsigned program_count() const
|
||||
{
|
||||
return header()->ph_num;
|
||||
}
|
||||
|
||||
/// Get a program header
|
||||
/// \arg index The index number of the program header
|
||||
/// \returns A pointer to the program header data
|
||||
const program_header * program(unsigned index) const;
|
||||
|
||||
/// Get the number of data sections in the image
|
||||
/// \returns The number of section entries
|
||||
inline unsigned section_count() const
|
||||
{
|
||||
return header()->sh_num;
|
||||
}
|
||||
|
||||
/// Get a section header
|
||||
/// \arg index The index number of the section header
|
||||
/// \returns A pointer to the section header data
|
||||
const section_header * section(unsigned index) const;
|
||||
|
||||
private:
|
||||
inline const file_header *header() const
|
||||
{
|
||||
return reinterpret_cast<const file_header *>(m_data);
|
||||
}
|
||||
|
||||
const void *m_data;
|
||||
size_t m_size;
|
||||
};
|
||||
|
||||
}
|
||||
98
src/libraries/elf/headers.h
Normal file
98
src/libraries/elf/headers.h
Normal file
@@ -0,0 +1,98 @@
|
||||
#pragma once
|
||||
#include <stdint.h>
|
||||
#include "kutil/enum_bitfields.h"
|
||||
|
||||
namespace elf {
|
||||
|
||||
enum class wordsize : uint8_t { invalid, bits32, bits64 };
|
||||
enum class encoding : uint8_t { invalid, lsb, msb };
|
||||
enum class osabi : uint8_t { sysV, hpux, standalone = 255 };
|
||||
enum class machine : uint16_t { none, x64 = 0x3e };
|
||||
|
||||
enum class filetype : uint16_t
|
||||
{
|
||||
none,
|
||||
relocatable,
|
||||
executable,
|
||||
shared,
|
||||
core
|
||||
};
|
||||
|
||||
|
||||
struct file_header
|
||||
{
|
||||
uint32_t magic;
|
||||
|
||||
wordsize word_size;
|
||||
encoding endianness;
|
||||
uint8_t ident_version;
|
||||
osabi os_abi;
|
||||
|
||||
uint64_t reserved;
|
||||
|
||||
filetype file_type;
|
||||
machine machine_type;
|
||||
|
||||
uint32_t version;
|
||||
|
||||
uint64_t entrypoint;
|
||||
uint64_t ph_offset;
|
||||
uint64_t sh_offset;
|
||||
|
||||
uint32_t flags;
|
||||
|
||||
uint16_t eh_size;
|
||||
|
||||
uint16_t ph_entsize;
|
||||
uint16_t ph_num;
|
||||
|
||||
uint16_t sh_entsize;
|
||||
uint16_t sh_num;
|
||||
|
||||
uint16_t sh_str_idx;
|
||||
} __attribute__ ((packed));
|
||||
|
||||
|
||||
enum class segment_type : uint32_t { null, load, dynamic, interpreter, note };
|
||||
|
||||
struct program_header
|
||||
{
|
||||
segment_type type;
|
||||
uint32_t flags;
|
||||
uint64_t offset;
|
||||
|
||||
uint64_t vaddr;
|
||||
uint64_t paddr;
|
||||
|
||||
uint64_t file_size;
|
||||
uint64_t mem_size;
|
||||
|
||||
uint64_t align;
|
||||
} __attribute__ ((packed));
|
||||
|
||||
|
||||
enum class section_type : uint32_t { null, progbits };
|
||||
enum class section_flags : uint64_t
|
||||
{
|
||||
write = 0x01,
|
||||
alloc = 0x02,
|
||||
exec = 0x04,
|
||||
};
|
||||
|
||||
struct section_header
|
||||
{
|
||||
uint32_t name_offset;
|
||||
section_type type;
|
||||
section_flags flags;
|
||||
uint64_t addr;
|
||||
uint64_t offset;
|
||||
uint64_t size;
|
||||
uint32_t link;
|
||||
uint32_t info;
|
||||
uint64_t align;
|
||||
uint64_t entry_size;
|
||||
} __attribute__ ((packed));
|
||||
|
||||
} // namespace elf
|
||||
|
||||
IS_BITFIELD(elf::section_flags);
|
||||
14
src/libraries/elf/wscript
Normal file
14
src/libraries/elf/wscript
Normal file
@@ -0,0 +1,14 @@
|
||||
|
||||
def configure(ctx):
|
||||
pass
|
||||
|
||||
def build(bld):
|
||||
sources = bld.path.ant_glob("**/*.cpp")
|
||||
|
||||
bld.stlib(
|
||||
source = sources,
|
||||
name = 'elf',
|
||||
target = 'elf',
|
||||
)
|
||||
|
||||
# vim: ft=python et
|
||||
Reference in New Issue
Block a user