BuildSystem: Move all userpace libraries under the userspace directory
As the number of libraries is increasing, root directory starts to expand. This adds better organization for libraries
This commit is contained in:
12
userspace/libraries/LibELF/CMakeLists.txt
Normal file
12
userspace/libraries/LibELF/CMakeLists.txt
Normal file
@@ -0,0 +1,12 @@
|
||||
cmake_minimum_required(VERSION 3.26)
|
||||
|
||||
project(LibELF CXX)
|
||||
|
||||
add_custom_target(libelf-headers
|
||||
COMMAND ${CMAKE_COMMAND} -E copy_directory_if_different ${CMAKE_CURRENT_SOURCE_DIR}/include/ ${BANAN_INCLUDE}/
|
||||
DEPENDS sysroot
|
||||
)
|
||||
|
||||
add_custom_target(libelf-install
|
||||
DEPENDS libelf-headers
|
||||
)
|
||||
405
userspace/libraries/LibELF/LibELF/ELF.cpp
Normal file
405
userspace/libraries/LibELF/LibELF/ELF.cpp
Normal file
@@ -0,0 +1,405 @@
|
||||
#include <BAN/ScopeGuard.h>
|
||||
#include <LibELF/ELF.h>
|
||||
#include <LibELF/Values.h>
|
||||
|
||||
#ifdef __is_kernel
|
||||
#include <kernel/FS/VirtualFileSystem.h>
|
||||
#include <kernel/Process.h>
|
||||
#endif
|
||||
|
||||
#include <fcntl.h>
|
||||
|
||||
#define ELF_PRINT_HEADERS 0
|
||||
|
||||
#ifdef __is_kernel
|
||||
extern uint8_t g_kernel_end[];
|
||||
using namespace Kernel;
|
||||
#endif
|
||||
|
||||
namespace LibELF
|
||||
{
|
||||
|
||||
#ifdef __is_kernel
|
||||
BAN::ErrorOr<BAN::UniqPtr<ELF>> ELF::load_from_file(BAN::RefPtr<Inode> inode)
|
||||
{
|
||||
BAN::Vector<uint8_t> buffer;
|
||||
TRY(buffer.resize(inode->size()));
|
||||
|
||||
TRY(inode->read(0, buffer.data(), inode->size()));
|
||||
|
||||
ELF* elf_ptr = new ELF(BAN::move(buffer));
|
||||
if (elf_ptr == nullptr)
|
||||
return BAN::Error::from_errno(ENOMEM);
|
||||
|
||||
auto elf = BAN::UniqPtr<ELF>::adopt(elf_ptr);
|
||||
TRY(elf->load());
|
||||
|
||||
return BAN::move(elf);
|
||||
}
|
||||
#else
|
||||
BAN::ErrorOr<ELF*> ELF::load_from_file(BAN::StringView file_path)
|
||||
{
|
||||
ELF* elf = nullptr;
|
||||
|
||||
{
|
||||
BAN::Vector<uint8_t> data;
|
||||
|
||||
int fd = TRY(Kernel::Process::current().open(file_path, O_RDONLY));
|
||||
BAN::ScopeGuard _([fd] { MUST(Kernel::Process::current().close(fd)); });
|
||||
|
||||
struct stat st;
|
||||
TRY(Kernel::Process::current().fstat(fd, &st));
|
||||
|
||||
TRY(data.resize(st.st_size));
|
||||
|
||||
TRY(Kernel::Process::current().read(fd, data.data(), data.size()));
|
||||
|
||||
elf = new ELF(BAN::move(data));
|
||||
ASSERT(elf);
|
||||
}
|
||||
|
||||
if (auto res = elf->load(); res.is_error())
|
||||
{
|
||||
delete elf;
|
||||
return res.error();
|
||||
}
|
||||
|
||||
return elf;
|
||||
}
|
||||
#endif
|
||||
|
||||
BAN::ErrorOr<void> ELF::load()
|
||||
{
|
||||
if (m_data.size() < EI_NIDENT)
|
||||
{
|
||||
dprintln("Too small ELF file");
|
||||
return BAN::Error::from_errno(EINVAL);
|
||||
}
|
||||
|
||||
if (m_data[EI_MAG0] != ELFMAG0 ||
|
||||
m_data[EI_MAG1] != ELFMAG1 ||
|
||||
m_data[EI_MAG2] != ELFMAG2 ||
|
||||
m_data[EI_MAG3] != ELFMAG3)
|
||||
{
|
||||
dprintln("Invalid ELF header");
|
||||
return BAN::Error::from_errno(EINVAL);
|
||||
}
|
||||
|
||||
if (m_data[EI_DATA] != ELFDATA2LSB)
|
||||
{
|
||||
dprintln("Only little-endian is supported");
|
||||
return BAN::Error::from_errno(EINVAL);
|
||||
}
|
||||
|
||||
if (m_data[EI_VERSION] != EV_CURRENT)
|
||||
{
|
||||
dprintln("Invalid ELF version");
|
||||
return BAN::Error::from_errno(EINVAL);
|
||||
}
|
||||
|
||||
if (m_data[EI_CLASS] == ELFCLASS64)
|
||||
{
|
||||
if (m_data.size() <= sizeof(Elf64FileHeader))
|
||||
{
|
||||
dprintln("Too small ELF file");
|
||||
return BAN::Error::from_errno(EINVAL);
|
||||
}
|
||||
|
||||
auto& header = file_header64();
|
||||
if (!parse_elf64_file_header(header))
|
||||
return BAN::Error::from_errno(EINVAL);
|
||||
|
||||
for (size_t i = 0; i < header.e_phnum; i++)
|
||||
{
|
||||
auto& program_header = program_header64(i);
|
||||
if (!parse_elf64_program_header(program_header))
|
||||
return BAN::Error::from_errno(EINVAL);
|
||||
}
|
||||
|
||||
for (size_t i = 1; i < header.e_shnum; i++)
|
||||
{
|
||||
auto& section_header = section_header64(i);
|
||||
if (!parse_elf64_section_header(section_header))
|
||||
return BAN::Error::from_errno(EINVAL);
|
||||
}
|
||||
}
|
||||
else if (m_data[EI_CLASS] == ELFCLASS32)
|
||||
{
|
||||
if (m_data.size() <= sizeof(Elf32FileHeader))
|
||||
{
|
||||
dprintln("Too small ELF file");
|
||||
return BAN::Error::from_errno(EINVAL);
|
||||
}
|
||||
|
||||
auto& header = file_header32();
|
||||
if (!parse_elf32_file_header(header))
|
||||
return BAN::Error::from_errno(EINVAL);
|
||||
|
||||
for (size_t i = 0; i < header.e_phnum; i++)
|
||||
{
|
||||
auto& program_header = program_header32(i);
|
||||
if (!parse_elf32_program_header(program_header))
|
||||
return BAN::Error::from_errno(EINVAL);
|
||||
}
|
||||
|
||||
for (size_t i = 1; i < header.e_shnum; i++)
|
||||
{
|
||||
auto& section_header = section_header32(i);
|
||||
if (!parse_elf32_section_header(section_header))
|
||||
return BAN::Error::from_errno(EINVAL);
|
||||
}
|
||||
}
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
bool ELF::is_x86_32() const { return m_data[EI_CLASS] == ELFCLASS32; }
|
||||
bool ELF::is_x86_64() const { return m_data[EI_CLASS] == ELFCLASS64; }
|
||||
|
||||
/*
|
||||
|
||||
64 bit ELF
|
||||
|
||||
*/
|
||||
|
||||
const char* ELF::lookup_section_name64(uint32_t offset) const
|
||||
{
|
||||
return lookup_string64(file_header64().e_shstrndx, offset);
|
||||
}
|
||||
|
||||
const char* ELF::lookup_string64(size_t table_index, uint32_t offset) const
|
||||
{
|
||||
if (table_index == SHN_UNDEF)
|
||||
return nullptr;
|
||||
auto& section_header = section_header64(table_index);
|
||||
return (const char*)m_data.data() + section_header.sh_offset + offset;
|
||||
}
|
||||
|
||||
bool ELF::parse_elf64_file_header(const Elf64FileHeader& header)
|
||||
{
|
||||
if (header.e_type != ET_EXEC)
|
||||
{
|
||||
dprintln("Only executable files are supported");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (header.e_version != EV_CURRENT)
|
||||
{
|
||||
dprintln("Invalid ELF version");
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ELF::parse_elf64_program_header(const Elf64ProgramHeader& header)
|
||||
{
|
||||
#if ELF_PRINT_HEADERS
|
||||
dprintln("program header");
|
||||
dprintln(" type {H}", header.p_type);
|
||||
dprintln(" flags {H}", header.p_flags);
|
||||
dprintln(" offset {H}", header.p_offset);
|
||||
dprintln(" vaddr {H}", header.p_vaddr);
|
||||
dprintln(" paddr {H}", header.p_paddr);
|
||||
dprintln(" filesz {}", header.p_filesz);
|
||||
dprintln(" memsz {}", header.p_memsz);
|
||||
dprintln(" align {}", header.p_align);
|
||||
#endif
|
||||
(void)header;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ELF::parse_elf64_section_header(const Elf64SectionHeader& header)
|
||||
{
|
||||
#if ELF_PRINT_HEADERS
|
||||
if (auto* name = lookup_section_name64(header.sh_name))
|
||||
dprintln("{}", name);
|
||||
|
||||
switch (header.sh_type)
|
||||
{
|
||||
case SHT_NULL:
|
||||
dprintln(" SHT_NULL");
|
||||
break;
|
||||
case SHT_PROGBITS:
|
||||
dprintln(" SHT_PROGBITS");
|
||||
break;
|
||||
case SHT_SYMTAB:
|
||||
for (size_t i = 1; i < header.sh_size / header.sh_entsize; i++)
|
||||
{
|
||||
auto& symbol = ((const Elf64Symbol*)(m_data.data() + header.sh_offset))[i];
|
||||
if (auto* name = lookup_string64(header.sh_link, symbol.st_name))
|
||||
dprintln(" {}", name);
|
||||
}
|
||||
break;
|
||||
case SHT_STRTAB:
|
||||
dprintln(" SHT_STRTAB");
|
||||
break;
|
||||
case SHT_RELA:
|
||||
dprintln(" SHT_RELA");
|
||||
break;
|
||||
case SHT_NOBITS:
|
||||
dprintln(" SHT_NOBITS");
|
||||
break;
|
||||
case SHT_REL:
|
||||
dprintln(" SHT_REL");
|
||||
break;
|
||||
case SHT_SHLIB:
|
||||
dprintln(" SHT_SHLIB");
|
||||
break;
|
||||
case SHT_DYNSYM:
|
||||
dprintln(" SHT_DYNSYM");
|
||||
break;
|
||||
default:
|
||||
ASSERT(false);
|
||||
}
|
||||
#endif
|
||||
(void)header;
|
||||
return true;
|
||||
}
|
||||
|
||||
const Elf64FileHeader& ELF::file_header64() const
|
||||
{
|
||||
ASSERT(is_x86_64());
|
||||
return *(const Elf64FileHeader*)m_data.data();
|
||||
}
|
||||
|
||||
const Elf64ProgramHeader& ELF::program_header64(size_t index) const
|
||||
{
|
||||
ASSERT(is_x86_64());
|
||||
const auto& file_header = file_header64();
|
||||
ASSERT(index < file_header.e_phnum);
|
||||
return *(const Elf64ProgramHeader*)(m_data.data() + file_header.e_phoff + file_header.e_phentsize * index);
|
||||
}
|
||||
|
||||
const Elf64SectionHeader& ELF::section_header64(size_t index) const
|
||||
{
|
||||
ASSERT(is_x86_64());
|
||||
const auto& file_header = file_header64();
|
||||
ASSERT(index < file_header.e_shnum);
|
||||
return *(const Elf64SectionHeader*)(m_data.data() + file_header.e_shoff + file_header.e_shentsize * index);
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
32 bit ELF
|
||||
|
||||
*/
|
||||
|
||||
const char* ELF::lookup_section_name32(uint32_t offset) const
|
||||
{
|
||||
return lookup_string32(file_header32().e_shstrndx, offset);
|
||||
}
|
||||
|
||||
const char* ELF::lookup_string32(size_t table_index, uint32_t offset) const
|
||||
{
|
||||
if (table_index == SHN_UNDEF)
|
||||
return nullptr;
|
||||
auto& section_header = section_header32(table_index);
|
||||
return (const char*)m_data.data() + section_header.sh_offset + offset;
|
||||
}
|
||||
|
||||
bool ELF::parse_elf32_file_header(const Elf32FileHeader& header)
|
||||
{
|
||||
if (header.e_type != ET_EXEC)
|
||||
{
|
||||
dprintln("Only executable files are supported");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (header.e_version != EV_CURRENT)
|
||||
{
|
||||
dprintln("Invalid ELF version");
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ELF::parse_elf32_program_header(const Elf32ProgramHeader& header)
|
||||
{
|
||||
#if ELF_PRINT_HEADERS
|
||||
dprintln("program header");
|
||||
dprintln(" type {H}", header.p_type);
|
||||
dprintln(" flags {H}", header.p_flags);
|
||||
dprintln(" offset {H}", header.p_offset);
|
||||
dprintln(" vaddr {H}", header.p_vaddr);
|
||||
dprintln(" paddr {H}", header.p_paddr);
|
||||
dprintln(" filesz {}", header.p_filesz);
|
||||
dprintln(" memsz {}", header.p_memsz);
|
||||
dprintln(" align {}", header.p_align);
|
||||
#endif
|
||||
(void)header;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ELF::parse_elf32_section_header(const Elf32SectionHeader& header)
|
||||
{
|
||||
#if ELF_PRINT_HEADERS
|
||||
if (auto* name = lookup_section_name32(header.sh_name))
|
||||
dprintln("{}", name);
|
||||
|
||||
switch (header.sh_type)
|
||||
{
|
||||
case SHT_NULL:
|
||||
dprintln(" SHT_NULL");
|
||||
break;
|
||||
case SHT_PROGBITS:
|
||||
dprintln(" SHT_PROGBITS");
|
||||
break;
|
||||
case SHT_SYMTAB:
|
||||
for (size_t i = 1; i < header.sh_size / header.sh_entsize; i++)
|
||||
{
|
||||
auto& symbol = ((const Elf32Symbol*)(m_data.data() + header.sh_offset))[i];
|
||||
if (auto* name = lookup_string32(header.sh_link, symbol.st_name))
|
||||
dprintln(" {}", name);
|
||||
}
|
||||
break;
|
||||
case SHT_STRTAB:
|
||||
dprintln(" SHT_STRTAB");
|
||||
break;
|
||||
case SHT_RELA:
|
||||
dprintln(" SHT_RELA");
|
||||
break;
|
||||
case SHT_NOBITS:
|
||||
dprintln(" SHT_NOBITS");
|
||||
break;
|
||||
case SHT_REL:
|
||||
dprintln(" SHT_REL");
|
||||
break;
|
||||
case SHT_SHLIB:
|
||||
dprintln(" SHT_SHLIB");
|
||||
break;
|
||||
case SHT_DYNSYM:
|
||||
dprintln(" SHT_DYNSYM");
|
||||
break;
|
||||
default:
|
||||
ASSERT(false);
|
||||
}
|
||||
#endif
|
||||
(void)header;
|
||||
return true;
|
||||
}
|
||||
|
||||
const Elf32FileHeader& ELF::file_header32() const
|
||||
{
|
||||
ASSERT(is_x86_32());
|
||||
return *(const Elf32FileHeader*)m_data.data();
|
||||
}
|
||||
|
||||
const Elf32ProgramHeader& ELF::program_header32(size_t index) const
|
||||
{
|
||||
ASSERT(is_x86_32());
|
||||
const auto& file_header = file_header32();
|
||||
ASSERT(index < file_header.e_phnum);
|
||||
return *(const Elf32ProgramHeader*)(m_data.data() + file_header.e_phoff + file_header.e_phentsize * index);
|
||||
}
|
||||
|
||||
const Elf32SectionHeader& ELF::section_header32(size_t index) const
|
||||
{
|
||||
ASSERT(is_x86_32());
|
||||
const auto& file_header = file_header32();
|
||||
ASSERT(index < file_header.e_shnum);
|
||||
return *(const Elf32SectionHeader*)(m_data.data() + file_header.e_shoff + file_header.e_shentsize * index);
|
||||
}
|
||||
|
||||
}
|
||||
331
userspace/libraries/LibELF/LibELF/LoadableELF.cpp
Normal file
331
userspace/libraries/LibELF/LibELF/LoadableELF.cpp
Normal file
@@ -0,0 +1,331 @@
|
||||
#include <BAN/ScopeGuard.h>
|
||||
#include <kernel/Memory/Heap.h>
|
||||
#include <kernel/Lock/LockGuard.h>
|
||||
#include <LibELF/LoadableELF.h>
|
||||
#include <LibELF/Values.h>
|
||||
|
||||
namespace LibELF
|
||||
{
|
||||
|
||||
using namespace Kernel;
|
||||
|
||||
BAN::ErrorOr<BAN::UniqPtr<LoadableELF>> LoadableELF::load_from_inode(PageTable& page_table, BAN::RefPtr<Inode> inode)
|
||||
{
|
||||
auto* elf_ptr = new LoadableELF(page_table, inode);
|
||||
if (elf_ptr == nullptr)
|
||||
return BAN::Error::from_errno(ENOMEM);
|
||||
auto elf = BAN::UniqPtr<LoadableELF>::adopt(elf_ptr);
|
||||
TRY(elf->initialize());
|
||||
return BAN::move(elf);
|
||||
}
|
||||
|
||||
LoadableELF::LoadableELF(PageTable& page_table, BAN::RefPtr<Inode> inode)
|
||||
: m_inode(inode)
|
||||
, m_page_table(page_table)
|
||||
{
|
||||
}
|
||||
|
||||
LoadableELF::~LoadableELF()
|
||||
{
|
||||
if (!m_loaded)
|
||||
return;
|
||||
for (const auto& program_header : m_program_headers)
|
||||
{
|
||||
switch (program_header.p_type)
|
||||
{
|
||||
case PT_NULL:
|
||||
continue;
|
||||
case PT_LOAD:
|
||||
{
|
||||
vaddr_t start = program_header.p_vaddr & PAGE_ADDR_MASK;
|
||||
size_t pages = range_page_count(program_header.p_vaddr, program_header.p_memsz);
|
||||
for (size_t i = 0; i < pages; i++)
|
||||
{
|
||||
paddr_t paddr = m_page_table.physical_address_of(start + i * PAGE_SIZE);
|
||||
if (paddr != 0)
|
||||
Heap::get().release_page(paddr);
|
||||
}
|
||||
m_page_table.unmap_range(start, pages * PAGE_SIZE);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
ASSERT_NOT_REACHED();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
BAN::ErrorOr<void> LoadableELF::initialize()
|
||||
{
|
||||
if ((size_t)m_inode->size() < sizeof(ElfNativeFileHeader))
|
||||
{
|
||||
dprintln("Too small file");
|
||||
return BAN::Error::from_errno(ENOEXEC);
|
||||
}
|
||||
|
||||
size_t nread = TRY(m_inode->read(0, BAN::ByteSpan::from(m_file_header)));
|
||||
ASSERT(nread == sizeof(m_file_header));
|
||||
|
||||
if (m_file_header.e_ident[EI_MAG0] != ELFMAG0 ||
|
||||
m_file_header.e_ident[EI_MAG1] != ELFMAG1 ||
|
||||
m_file_header.e_ident[EI_MAG2] != ELFMAG2 ||
|
||||
m_file_header.e_ident[EI_MAG3] != ELFMAG3)
|
||||
{
|
||||
dprintln("Invalid magic in header");
|
||||
return BAN::Error::from_errno(ENOEXEC);
|
||||
}
|
||||
|
||||
if (m_file_header.e_ident[EI_DATA] != ELFDATA2LSB)
|
||||
{
|
||||
dprintln("Only little-endian is supported");
|
||||
return BAN::Error::from_errno(ENOEXEC);
|
||||
}
|
||||
|
||||
if (m_file_header.e_ident[EI_VERSION] != EV_CURRENT)
|
||||
{
|
||||
dprintln("Invalid version");
|
||||
return BAN::Error::from_errno(ENOEXEC);
|
||||
}
|
||||
|
||||
#if ARCH(i686)
|
||||
if (m_file_header.e_ident[EI_CLASS] != ELFCLASS32)
|
||||
#elif ARCH(x86_64)
|
||||
if (m_file_header.e_ident[EI_CLASS] != ELFCLASS64)
|
||||
#endif
|
||||
{
|
||||
dprintln("Not in native format");
|
||||
return BAN::Error::from_errno(EINVAL);
|
||||
}
|
||||
|
||||
if (m_file_header.e_type != ET_EXEC)
|
||||
{
|
||||
dprintln("Only executable files are supported");
|
||||
return BAN::Error::from_errno(EINVAL);
|
||||
}
|
||||
|
||||
if (m_file_header.e_version != EV_CURRENT)
|
||||
{
|
||||
dprintln("Unsupported version");
|
||||
return BAN::Error::from_errno(EINVAL);
|
||||
}
|
||||
|
||||
ASSERT(m_file_header.e_phentsize <= sizeof(ElfNativeProgramHeader));
|
||||
|
||||
TRY(m_program_headers.resize(m_file_header.e_phnum));
|
||||
for (size_t i = 0; i < m_file_header.e_phnum; i++)
|
||||
{
|
||||
TRY(m_inode->read(m_file_header.e_phoff + m_file_header.e_phentsize * i, BAN::ByteSpan::from(m_program_headers[i])));
|
||||
|
||||
const auto& pheader = m_program_headers[i];
|
||||
if (pheader.p_type != PT_NULL && pheader.p_type != PT_LOAD)
|
||||
{
|
||||
dprintln("Unsupported program header type {}", pheader.p_type);
|
||||
return BAN::Error::from_errno(ENOTSUP);
|
||||
}
|
||||
if (pheader.p_memsz < pheader.p_filesz)
|
||||
{
|
||||
dprintln("Invalid program header");
|
||||
return BAN::Error::from_errno(EINVAL);
|
||||
}
|
||||
|
||||
m_virtual_page_count += BAN::Math::div_round_up<size_t>((pheader.p_vaddr % PAGE_SIZE) + pheader.p_memsz, PAGE_SIZE);
|
||||
}
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
vaddr_t LoadableELF::entry_point() const
|
||||
{
|
||||
return m_file_header.e_entry;
|
||||
}
|
||||
|
||||
bool LoadableELF::contains(vaddr_t address) const
|
||||
{
|
||||
for (const auto& program_header : m_program_headers)
|
||||
{
|
||||
switch (program_header.p_type)
|
||||
{
|
||||
case PT_NULL:
|
||||
continue;
|
||||
case PT_LOAD:
|
||||
if (program_header.p_vaddr <= address && address < program_header.p_vaddr + program_header.p_memsz)
|
||||
return true;
|
||||
break;
|
||||
default:
|
||||
ASSERT_NOT_REACHED();
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool LoadableELF::is_address_space_free() const
|
||||
{
|
||||
for (const auto& program_header : m_program_headers)
|
||||
{
|
||||
switch (program_header.p_type)
|
||||
{
|
||||
case PT_NULL:
|
||||
break;
|
||||
case PT_LOAD:
|
||||
{
|
||||
vaddr_t page_vaddr = program_header.p_vaddr & PAGE_ADDR_MASK;
|
||||
size_t pages = range_page_count(program_header.p_vaddr, program_header.p_memsz);
|
||||
if (!m_page_table.is_range_free(page_vaddr, pages * PAGE_SIZE))
|
||||
return false;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
ASSERT_NOT_REACHED();
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void LoadableELF::reserve_address_space()
|
||||
{
|
||||
for (const auto& program_header : m_program_headers)
|
||||
{
|
||||
switch (program_header.p_type)
|
||||
{
|
||||
case PT_NULL:
|
||||
break;
|
||||
case PT_LOAD:
|
||||
{
|
||||
vaddr_t page_vaddr = program_header.p_vaddr & PAGE_ADDR_MASK;
|
||||
size_t pages = range_page_count(program_header.p_vaddr, program_header.p_memsz);
|
||||
ASSERT(m_page_table.reserve_range(page_vaddr, pages * PAGE_SIZE));
|
||||
break;
|
||||
}
|
||||
default:
|
||||
ASSERT_NOT_REACHED();
|
||||
}
|
||||
}
|
||||
m_loaded = true;
|
||||
}
|
||||
|
||||
void LoadableELF::update_suid_sgid(Kernel::Credentials& credentials)
|
||||
{
|
||||
if (m_inode->mode().mode & +Inode::Mode::ISUID)
|
||||
credentials.set_euid(m_inode->uid());
|
||||
if (m_inode->mode().mode & +Inode::Mode::ISGID)
|
||||
credentials.set_egid(m_inode->gid());
|
||||
}
|
||||
|
||||
BAN::ErrorOr<void> LoadableELF::load_page_to_memory(vaddr_t address)
|
||||
{
|
||||
for (const auto& program_header : m_program_headers)
|
||||
{
|
||||
switch (program_header.p_type)
|
||||
{
|
||||
case PT_NULL:
|
||||
break;
|
||||
case PT_LOAD:
|
||||
{
|
||||
if (!(program_header.p_vaddr <= address && address < program_header.p_vaddr + program_header.p_memsz))
|
||||
continue;
|
||||
|
||||
PageTable::flags_t flags = PageTable::Flags::UserSupervisor | PageTable::Flags::Present;
|
||||
if (program_header.p_flags & LibELF::PF_W)
|
||||
flags |= PageTable::Flags::ReadWrite;
|
||||
if (program_header.p_flags & LibELF::PF_X)
|
||||
flags |= PageTable::Flags::Execute;
|
||||
|
||||
vaddr_t vaddr = address & PAGE_ADDR_MASK;
|
||||
paddr_t paddr = Heap::get().take_free_page();
|
||||
if (paddr == 0)
|
||||
return BAN::Error::from_errno(ENOMEM);
|
||||
|
||||
// Temporarily map page as RW so kernel can write to it
|
||||
m_page_table.map_page_at(paddr, vaddr, PageTable::Flags::ReadWrite | PageTable::Flags::Present);
|
||||
m_physical_page_count++;
|
||||
|
||||
memset((void*)vaddr, 0x00, PAGE_SIZE);
|
||||
|
||||
if (vaddr / PAGE_SIZE < BAN::Math::div_round_up<size_t>(program_header.p_vaddr + program_header.p_filesz, PAGE_SIZE))
|
||||
{
|
||||
size_t vaddr_offset = 0;
|
||||
if (vaddr < program_header.p_vaddr)
|
||||
vaddr_offset = program_header.p_vaddr - vaddr;
|
||||
|
||||
size_t file_offset = 0;
|
||||
if (vaddr > program_header.p_vaddr)
|
||||
file_offset = vaddr - program_header.p_vaddr;
|
||||
|
||||
size_t bytes = BAN::Math::min<size_t>(PAGE_SIZE - vaddr_offset, program_header.p_filesz - file_offset);
|
||||
TRY(m_inode->read(program_header.p_offset + file_offset, { (uint8_t*)vaddr + vaddr_offset, bytes }));
|
||||
}
|
||||
|
||||
// Map page with the correct flags
|
||||
m_page_table.map_page_at(paddr, vaddr, flags);
|
||||
|
||||
return {};
|
||||
}
|
||||
default:
|
||||
ASSERT_NOT_REACHED();
|
||||
}
|
||||
}
|
||||
ASSERT_NOT_REACHED();
|
||||
}
|
||||
|
||||
|
||||
BAN::ErrorOr<BAN::UniqPtr<LoadableELF>> LoadableELF::clone(Kernel::PageTable& new_page_table)
|
||||
{
|
||||
auto* elf_ptr = new LoadableELF(new_page_table, m_inode);
|
||||
if (elf_ptr == nullptr)
|
||||
return BAN::Error::from_errno(ENOMEM);
|
||||
auto elf = BAN::UniqPtr<LoadableELF>::adopt(elf_ptr);
|
||||
|
||||
memcpy(&elf->m_file_header, &m_file_header, sizeof(ElfNativeFileHeader));
|
||||
|
||||
TRY(elf->m_program_headers.resize(m_program_headers.size()));
|
||||
memcpy(elf->m_program_headers.data(), m_program_headers.data(), m_program_headers.size() * sizeof(ElfNativeProgramHeader));
|
||||
|
||||
elf->reserve_address_space();
|
||||
|
||||
for (const auto& program_header : m_program_headers)
|
||||
{
|
||||
switch (program_header.p_type)
|
||||
{
|
||||
case PT_NULL:
|
||||
break;
|
||||
case PT_LOAD:
|
||||
{
|
||||
if (!(program_header.p_flags & LibELF::PF_W))
|
||||
continue;
|
||||
|
||||
PageTable::flags_t flags = PageTable::Flags::UserSupervisor | PageTable::Flags::Present;
|
||||
if (program_header.p_flags & LibELF::PF_W)
|
||||
flags |= PageTable::Flags::ReadWrite;
|
||||
if (program_header.p_flags & LibELF::PF_X)
|
||||
flags |= PageTable::Flags::Execute;
|
||||
|
||||
vaddr_t start = program_header.p_vaddr & PAGE_ADDR_MASK;
|
||||
size_t pages = range_page_count(program_header.p_vaddr, program_header.p_memsz);
|
||||
|
||||
for (size_t i = 0; i < pages; i++)
|
||||
{
|
||||
if (m_page_table.physical_address_of(start + i * PAGE_SIZE) == 0)
|
||||
continue;
|
||||
|
||||
paddr_t paddr = Heap::get().take_free_page();
|
||||
if (paddr == 0)
|
||||
return BAN::Error::from_errno(ENOMEM);
|
||||
|
||||
PageTable::with_fast_page(paddr, [&] {
|
||||
memcpy(PageTable::fast_page_as_ptr(), (void*)(start + i * PAGE_SIZE), PAGE_SIZE);
|
||||
});
|
||||
|
||||
new_page_table.map_page_at(paddr, start + i * PAGE_SIZE, flags);
|
||||
elf->m_physical_page_count++;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
default:
|
||||
ASSERT_NOT_REACHED();
|
||||
}
|
||||
}
|
||||
|
||||
return elf;
|
||||
}
|
||||
|
||||
}
|
||||
89
userspace/libraries/LibELF/include/LibELF/ELF.h
Normal file
89
userspace/libraries/LibELF/include/LibELF/ELF.h
Normal file
@@ -0,0 +1,89 @@
|
||||
#pragma once
|
||||
|
||||
#ifdef __is_kernel
|
||||
#include <kernel/FS/Inode.h>
|
||||
#include <kernel/Memory/VirtualRange.h>
|
||||
#endif
|
||||
|
||||
#include <BAN/StringView.h>
|
||||
#include <BAN/UniqPtr.h>
|
||||
#include <BAN/Vector.h>
|
||||
#include <kernel/Arch.h>
|
||||
#include "Types.h"
|
||||
|
||||
namespace LibELF
|
||||
{
|
||||
|
||||
class ELF
|
||||
{
|
||||
public:
|
||||
#ifdef __is_kernel
|
||||
static BAN::ErrorOr<BAN::UniqPtr<ELF>> load_from_file(BAN::RefPtr<Kernel::Inode>);
|
||||
#else
|
||||
static BAN::ErrorOr<BAN::UniqPtr<ELF>> load_from_file(BAN::StringView);
|
||||
#endif
|
||||
|
||||
const Elf64FileHeader& file_header64() const;
|
||||
const Elf64ProgramHeader& program_header64(size_t) const;
|
||||
const Elf64SectionHeader& section_header64(size_t) const;
|
||||
const char* lookup_section_name64(uint32_t) const;
|
||||
const char* lookup_string64(size_t, uint32_t) const;
|
||||
#if ARCH(x86_64)
|
||||
const Elf64FileHeader& file_header_native() const { return file_header64(); }
|
||||
const Elf64ProgramHeader& program_header_native(size_t index) const { return program_header64(index); }
|
||||
const Elf64SectionHeader& section_header_native(size_t index) const { return section_header64(index); }
|
||||
const char* lookup_section_name_native(uint32_t offset) const { return lookup_section_name64(offset); }
|
||||
const char* lookup_string_native(size_t table_index, uint32_t offset) const { return lookup_string64(table_index, offset); }
|
||||
bool is_native() const { return is_x86_64(); }
|
||||
#endif
|
||||
|
||||
const Elf32FileHeader& file_header32() const;
|
||||
const Elf32ProgramHeader& program_header32(size_t) const;
|
||||
const Elf32SectionHeader& section_header32(size_t) const;
|
||||
const char* lookup_section_name32(uint32_t) const;
|
||||
const char* lookup_string32(size_t, uint32_t) const;
|
||||
#if ARCH(i686)
|
||||
const Elf32FileHeader& file_header_native() const { return file_header32(); }
|
||||
const Elf32ProgramHeader& program_header_native(size_t index) const { return program_header32(index); }
|
||||
const Elf32SectionHeader& section_header_native(size_t index) const { return section_header32(index); }
|
||||
const char* lookup_section_name_native(uint32_t offset) const { return lookup_section_name32(offset); }
|
||||
const char* lookup_string_native(size_t table_index, uint32_t offset) const { return lookup_string32(table_index, offset); }
|
||||
bool is_native() const { return is_x86_32(); }
|
||||
#endif
|
||||
|
||||
const uint8_t* data() const { return m_data.data(); }
|
||||
|
||||
bool is_x86_32() const;
|
||||
bool is_x86_64() const;
|
||||
|
||||
private:
|
||||
//#ifdef __is_kernel
|
||||
// ELF(BAN::UniqPtr<Kernel::VirtualRange>&& storage, size_t size)
|
||||
// : m_storage(BAN::move(storage))
|
||||
// , m_data((const uint8_t*)m_storage->vaddr(), size)
|
||||
// {}
|
||||
//#else
|
||||
ELF(BAN::Vector<uint8_t>&& data)
|
||||
: m_data(BAN::move(data))
|
||||
{}
|
||||
//#endif
|
||||
BAN::ErrorOr<void> load();
|
||||
|
||||
bool parse_elf64_file_header(const Elf64FileHeader&);
|
||||
bool parse_elf64_program_header(const Elf64ProgramHeader&);
|
||||
bool parse_elf64_section_header(const Elf64SectionHeader&);
|
||||
|
||||
bool parse_elf32_file_header(const Elf32FileHeader&);
|
||||
bool parse_elf32_program_header(const Elf32ProgramHeader&);
|
||||
bool parse_elf32_section_header(const Elf32SectionHeader&);
|
||||
|
||||
private:
|
||||
//#ifdef __is_kernel
|
||||
// BAN::UniqPtr<Kernel::VirtualRange> m_storage;
|
||||
// BAN::Span<const uint8_t> m_data;
|
||||
//#else
|
||||
const BAN::Vector<uint8_t> m_data;
|
||||
//#endif
|
||||
};
|
||||
|
||||
}
|
||||
57
userspace/libraries/LibELF/include/LibELF/LoadableELF.h
Normal file
57
userspace/libraries/LibELF/include/LibELF/LoadableELF.h
Normal file
@@ -0,0 +1,57 @@
|
||||
#pragma once
|
||||
|
||||
#ifndef __is_kernel
|
||||
#error "This is kernel only header"
|
||||
#endif
|
||||
|
||||
#include <BAN/UniqPtr.h>
|
||||
#include <BAN/Vector.h>
|
||||
|
||||
#include <kernel/Credentials.h>
|
||||
#include <kernel/FS/Inode.h>
|
||||
#include <kernel/Memory/PageTable.h>
|
||||
|
||||
#include <LibELF/Types.h>
|
||||
|
||||
namespace LibELF
|
||||
{
|
||||
|
||||
class LoadableELF
|
||||
{
|
||||
BAN_NON_COPYABLE(LoadableELF);
|
||||
BAN_NON_MOVABLE(LoadableELF);
|
||||
|
||||
public:
|
||||
static BAN::ErrorOr<BAN::UniqPtr<LoadableELF>> load_from_inode(Kernel::PageTable&, BAN::RefPtr<Kernel::Inode>);
|
||||
~LoadableELF();
|
||||
|
||||
Kernel::vaddr_t entry_point() const;
|
||||
|
||||
bool contains(Kernel::vaddr_t address) const;
|
||||
bool is_address_space_free() const;
|
||||
void reserve_address_space();
|
||||
|
||||
void update_suid_sgid(Kernel::Credentials&);
|
||||
|
||||
BAN::ErrorOr<void> load_page_to_memory(Kernel::vaddr_t address);
|
||||
|
||||
BAN::ErrorOr<BAN::UniqPtr<LoadableELF>> clone(Kernel::PageTable&);
|
||||
|
||||
size_t virtual_page_count() const { return m_virtual_page_count; }
|
||||
size_t physical_page_count() const { return m_physical_page_count; }
|
||||
|
||||
private:
|
||||
LoadableELF(Kernel::PageTable&, BAN::RefPtr<Kernel::Inode>);
|
||||
BAN::ErrorOr<void> initialize();
|
||||
|
||||
private:
|
||||
BAN::RefPtr<Kernel::Inode> m_inode;
|
||||
Kernel::PageTable& m_page_table;
|
||||
ElfNativeFileHeader m_file_header;
|
||||
BAN::Vector<ElfNativeProgramHeader> m_program_headers;
|
||||
size_t m_virtual_page_count = 0;
|
||||
size_t m_physical_page_count = 0;
|
||||
bool m_loaded { false };
|
||||
};
|
||||
|
||||
}
|
||||
186
userspace/libraries/LibELF/include/LibELF/Types.h
Normal file
186
userspace/libraries/LibELF/include/LibELF/Types.h
Normal file
@@ -0,0 +1,186 @@
|
||||
#pragma once
|
||||
|
||||
#include <kernel/Arch.h>
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
namespace LibELF
|
||||
{
|
||||
|
||||
using Elf32Addr = uint32_t;
|
||||
using Elf32Off = uint32_t;
|
||||
using Elf32Half = uint16_t;
|
||||
using Elf32Word = uint32_t;
|
||||
using Elf32Sword = int32_t;
|
||||
|
||||
struct Elf32FileHeader
|
||||
{
|
||||
unsigned char e_ident[16];
|
||||
Elf32Half e_type;
|
||||
Elf32Half e_machine;
|
||||
Elf32Word e_version;
|
||||
Elf32Addr e_entry;
|
||||
Elf32Off e_phoff;
|
||||
Elf32Off e_shoff;
|
||||
Elf32Word e_flags;
|
||||
Elf32Half e_ehsize;
|
||||
Elf32Half e_phentsize;
|
||||
Elf32Half e_phnum;
|
||||
Elf32Half e_shentsize;
|
||||
Elf32Half e_shnum;
|
||||
Elf32Half e_shstrndx;
|
||||
};
|
||||
|
||||
struct Elf32SectionHeader
|
||||
{
|
||||
Elf32Word sh_name;
|
||||
Elf32Word sh_type;
|
||||
Elf32Word sh_flags;
|
||||
Elf32Addr sh_addr;
|
||||
Elf32Off sh_offset;
|
||||
Elf32Word sh_size;
|
||||
Elf32Word sh_link;
|
||||
Elf32Word sh_info;
|
||||
Elf32Word sh_addralign;
|
||||
Elf32Word sh_entsize;
|
||||
};
|
||||
|
||||
struct Elf32Symbol
|
||||
{
|
||||
Elf32Word st_name;
|
||||
Elf32Addr st_value;
|
||||
Elf32Word st_size;
|
||||
unsigned char st_info;
|
||||
unsigned char st_other;
|
||||
Elf32Half st_shndx;
|
||||
};
|
||||
|
||||
struct Elf32Relocation
|
||||
{
|
||||
Elf32Addr r_offset;
|
||||
Elf32Word r_info;
|
||||
};
|
||||
|
||||
struct Elf32RelocationA
|
||||
{
|
||||
Elf32Addr r_offset;
|
||||
Elf32Word r_info;
|
||||
Elf32Sword r_addend;
|
||||
};
|
||||
|
||||
struct Elf32ProgramHeader
|
||||
{
|
||||
Elf32Word p_type;
|
||||
Elf32Off p_offset;
|
||||
Elf32Addr p_vaddr;
|
||||
Elf32Addr p_paddr;
|
||||
Elf32Word p_filesz;
|
||||
Elf32Word p_memsz;
|
||||
Elf32Word p_flags;
|
||||
Elf32Word p_align;
|
||||
};
|
||||
|
||||
using Elf64Addr = uint64_t;
|
||||
using Elf64Off = uint64_t;
|
||||
using Elf64Half = uint16_t;
|
||||
using Elf64Word = uint32_t;
|
||||
using Elf64Sword = int32_t;
|
||||
using Elf64Xword = uint64_t;
|
||||
using Elf64Sxword = int64_t;
|
||||
|
||||
struct Elf64FileHeader
|
||||
{
|
||||
unsigned char e_ident[16];
|
||||
Elf64Half e_type;
|
||||
Elf64Half e_machine;
|
||||
Elf64Word e_version;
|
||||
Elf64Addr e_entry;
|
||||
Elf64Off e_phoff;
|
||||
Elf64Off e_shoff;
|
||||
Elf64Word e_flags;
|
||||
Elf64Half e_ehsize;
|
||||
Elf64Half e_phentsize;
|
||||
Elf64Half e_phnum;
|
||||
Elf64Half e_shentsize;
|
||||
Elf64Half e_shnum;
|
||||
Elf64Half e_shstrndx;
|
||||
};
|
||||
|
||||
struct Elf64SectionHeader
|
||||
{
|
||||
Elf64Word sh_name;
|
||||
Elf64Word sh_type;
|
||||
Elf64Xword sh_flags;
|
||||
Elf64Addr sh_addr;
|
||||
Elf64Off sh_offset;
|
||||
Elf64Xword sh_size;
|
||||
Elf64Word sh_link;
|
||||
Elf64Word sh_info;
|
||||
Elf64Xword sh_addralign;
|
||||
Elf64Xword sh_entsize;
|
||||
};
|
||||
|
||||
struct Elf64Symbol
|
||||
{
|
||||
Elf64Word st_name;
|
||||
unsigned char st_info;
|
||||
unsigned char st_other;
|
||||
Elf64Half st_shndx;
|
||||
Elf64Addr st_value;
|
||||
Elf64Xword st_size;
|
||||
};
|
||||
|
||||
struct Elf64Relocation
|
||||
{
|
||||
Elf64Addr r_offset;
|
||||
Elf64Xword r_info;
|
||||
};
|
||||
|
||||
struct Elf64RelocationA
|
||||
{
|
||||
Elf64Addr r_offset;
|
||||
Elf64Xword r_info;
|
||||
Elf64Sxword r_addend;
|
||||
};
|
||||
|
||||
struct Elf64ProgramHeader
|
||||
{
|
||||
Elf64Word p_type;
|
||||
Elf64Word p_flags;
|
||||
Elf64Off p_offset;
|
||||
Elf64Addr p_vaddr;
|
||||
Elf64Addr p_paddr;
|
||||
Elf64Xword p_filesz;
|
||||
Elf64Xword p_memsz;
|
||||
Elf64Xword p_align;
|
||||
};
|
||||
|
||||
#if ARCH(i686)
|
||||
using ElfNativeAddr = Elf32Addr;
|
||||
using ElfNativeOff = Elf32Off;
|
||||
using ElfNativeHalf = Elf32Half;
|
||||
using ElfNativeWord = Elf32Word;
|
||||
using ElfNativeSword = Elf32Sword;
|
||||
using ElfNativeFileHeader = Elf32FileHeader;
|
||||
using ElfNativeSectionHeader = Elf32SectionHeader;
|
||||
using ElfNativeSymbol = Elf32Symbol;
|
||||
using ElfNativeRelocation = Elf32Relocation;
|
||||
using ElfNativeRelocationA = Elf32RelocationA;
|
||||
using ElfNativeProgramHeader = Elf32ProgramHeader;
|
||||
#elif ARCH(x86_64)
|
||||
using ElfNativeAddr = Elf64Addr;
|
||||
using ElfNativeOff = Elf64Off;
|
||||
using ElfNativeHalf = Elf64Half;
|
||||
using ElfNativeWord = Elf64Word;
|
||||
using ElfNativeSword = Elf64Sword;
|
||||
using ElfNativeXword = Elf64Xword;
|
||||
using ElfNativeSxword = Elf64Sxword;
|
||||
using ElfNativeFileHeader = Elf64FileHeader;
|
||||
using ElfNativeSectionHeader = Elf64SectionHeader;
|
||||
using ElfNativeSymbol = Elf64Symbol;
|
||||
using ElfNativeRelocation = Elf64Relocation;
|
||||
using ElfNativeRelocationA = Elf64RelocationA;
|
||||
using ElfNativeProgramHeader = Elf64ProgramHeader;
|
||||
#endif
|
||||
|
||||
}
|
||||
140
userspace/libraries/LibELF/include/LibELF/Values.h
Normal file
140
userspace/libraries/LibELF/include/LibELF/Values.h
Normal file
@@ -0,0 +1,140 @@
|
||||
#pragma once
|
||||
|
||||
namespace LibELF
|
||||
{
|
||||
|
||||
enum ELF_Ident
|
||||
{
|
||||
ELFMAG0 = 0x7F,
|
||||
ELFMAG1 = 'E',
|
||||
ELFMAG2 = 'L',
|
||||
ELFMAG3 = 'F',
|
||||
|
||||
ELFCLASSNONE = 0,
|
||||
ELFCLASS32 = 1,
|
||||
ELFCLASS64 = 2,
|
||||
|
||||
ELFDATANONE = 0,
|
||||
ELFDATA2LSB = 1,
|
||||
ELFDATA2MSB = 2,
|
||||
};
|
||||
|
||||
enum ELF_EI
|
||||
{
|
||||
EI_MAG0 = 0,
|
||||
EI_MAG1 = 1,
|
||||
EI_MAG2 = 2,
|
||||
EI_MAG3 = 3,
|
||||
EI_CLASS = 4,
|
||||
EI_DATA = 5,
|
||||
EI_VERSION = 6,
|
||||
EI_OSABI = 7,
|
||||
EI_ABIVERSION = 8,
|
||||
EI_NIDENT = 16,
|
||||
};
|
||||
|
||||
enum ELF_ET
|
||||
{
|
||||
ET_NONE = 0,
|
||||
ET_REL = 1,
|
||||
ET_EXEC = 2,
|
||||
ET_DYN = 3,
|
||||
ET_CORE = 4,
|
||||
ET_LOOS = 0xfe00,
|
||||
ET_HIOS = 0xfeff,
|
||||
ET_LOPROC = 0xff00,
|
||||
ET_HIPROC = 0xffff,
|
||||
};
|
||||
|
||||
enum ELF_EV
|
||||
{
|
||||
EV_NONE = 0,
|
||||
EV_CURRENT = 1,
|
||||
};
|
||||
|
||||
enum ELF_SHT
|
||||
{
|
||||
SHT_NULL = 0,
|
||||
SHT_PROGBITS = 1,
|
||||
SHT_SYMTAB = 2,
|
||||
SHT_STRTAB = 3,
|
||||
SHT_RELA = 4,
|
||||
SHT_NOBITS = 8,
|
||||
SHT_REL = 9,
|
||||
SHT_SHLIB = 10,
|
||||
SHT_DYNSYM = 11,
|
||||
SHT_LOOS = 0x60000000,
|
||||
SHT_HIOS = 0x6FFFFFFF,
|
||||
SHT_LOPROC = 0x70000000,
|
||||
SHT_HIPROC = 0x7FFFFFFF,
|
||||
};
|
||||
|
||||
enum ELF_SHF
|
||||
{
|
||||
SHF_WRITE = 0x1,
|
||||
SHF_ALLOC = 0x2,
|
||||
SHF_EXECINSTR = 0x4,
|
||||
SHF_MASKOS = 0x0F000000,
|
||||
SHF_MASKPROC = 0xF0000000,
|
||||
};
|
||||
|
||||
enum ELF_SHN
|
||||
{
|
||||
SHN_UNDEF = 0,
|
||||
SHN_LOPROC = 0xFF00,
|
||||
SHN_HIPROC = 0xFF1F,
|
||||
SHN_LOOS = 0xFF20,
|
||||
SHN_HIOS = 0xFF3F,
|
||||
SHN_ABS = 0xFFF1,
|
||||
SHN_COMMON = 0xFFF2,
|
||||
};
|
||||
|
||||
enum ELF_STB
|
||||
{
|
||||
STB_LOCAL = 0,
|
||||
STB_GLOBAL = 1,
|
||||
STB_WEAK = 2,
|
||||
STB_LOOS = 10,
|
||||
STB_HIOS = 12,
|
||||
STB_LOPROC = 13,
|
||||
STB_HIPROC = 15,
|
||||
};
|
||||
|
||||
enum ELF_STT
|
||||
{
|
||||
STT_NOTYPE = 0,
|
||||
STT_OBJECT = 1,
|
||||
STT_FUNC = 2,
|
||||
STT_SECTION = 3,
|
||||
STT_FILE = 4,
|
||||
STT_LOOS = 10,
|
||||
STT_HIOS = 12,
|
||||
STT_LOPROC = 13,
|
||||
STT_HIPROC = 15,
|
||||
};
|
||||
|
||||
enum ELF_PT
|
||||
{
|
||||
PT_NULL = 0,
|
||||
PT_LOAD = 1,
|
||||
PT_DYNAMIC = 2,
|
||||
PT_INTERP = 3,
|
||||
PT_NOTE = 4,
|
||||
PT_SHLIB = 5,
|
||||
PT_PHDR = 6,
|
||||
PT_LOOS = 0x60000000,
|
||||
PT_HIOS = 0x6FFFFFFF,
|
||||
PT_LOPROC = 0x70000000,
|
||||
PT_HIPROC = 0x7FFFFFFF,
|
||||
};
|
||||
|
||||
enum ELF_PF
|
||||
{
|
||||
PF_X = 0x1,
|
||||
PF_W = 0x2,
|
||||
PF_R = 0x4,
|
||||
PF_MASKOS = 0x00FF0000,
|
||||
PF_MASKPROC = 0xFF000000,
|
||||
};
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user