# HG changeset patch # User Paul Boddie # Date 1652282591 -7200 # Node ID 06b056cac249a10c9d6604df3deac85890f52f9e # Parent 224d34e52d8513b1240b45408bb144cb20cea5c5 Moved ELF payload processing abstractions to libexec. diff -r 224d34e52d85 -r 06b056cac249 libexec/include/exec/elf.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libexec/include/exec/elf.h Wed May 11 17:23:11 2022 +0200 @@ -0,0 +1,95 @@ +/* + * ELF payload decoding support. + * + * Copyright (C) 2022 Paul Boddie + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA + */ + +#include + + + +/* Generic program segment interface. */ + +class ProgramSegment +{ +public: + virtual bool loadable() = 0; + virtual offset_t file_contents() = 0; + virtual offset_t file_offset() = 0; + virtual l4_addr_t region_address() = 0; + virtual offset_t region_size() = 0; + virtual l4re_rm_flags_t region_flags() = 0; + + Segment *segment(); +}; + +template +class ProgramSegmentVariant : public ProgramSegment +{ +protected: + PROGRAM_HEADER *_header; + +public: + explicit ProgramSegmentVariant(PROGRAM_HEADER *header); + + bool loadable(); + offset_t file_contents(); + offset_t file_offset(); + l4_addr_t region_address(); + offset_t region_size(); + l4re_rm_flags_t region_flags(); +}; + + + +/* Generic interface for an ELF payload. */ + +class Payload +{ +public: + virtual l4_addr_t entry_point() = 0; + virtual offset_t header_extent() = 0; + virtual offset_t program_header_extent() = 0; + virtual unsigned int segments() = 0; + virtual ProgramSegment *segment(unsigned int i) = 0; +}; + +template +class PayloadVariant : public Payload +{ +protected: + HEADER *_header; + +public: + explicit PayloadVariant(HEADER *header); + + l4_addr_t entry_point(); + offset_t header_extent(); + offset_t program_header_extent(); + unsigned int segments(); + ProgramSegment *segment(unsigned int i); +}; + + + +/* Return the appropriate payload object. */ + +Payload *get_payload(char *buf); + +/* vim: tabstop=2 expandtab shiftwidth=2 +*/ diff -r 224d34e52d85 -r 06b056cac249 libexec/lib/src/Makefile --- a/libexec/lib/src/Makefile Wed May 11 16:37:05 2022 +0200 +++ b/libexec/lib/src/Makefile Wed May 11 17:23:11 2022 +0200 @@ -3,7 +3,7 @@ TARGET = libexec.a libexec.so PC_FILENAME = libexec -SRC_CC = process.cc segment.cc stack.cc +SRC_CC = elf.cc process.cc segment.cc stack.cc REQUIRES_LIBS = l4re_c-util libmem libipc libstdc++ libsystypes libfsclient PRIVATE_INCDIR += $(PKGDIR)/include/exec diff -r 224d34e52d85 -r 06b056cac249 libexec/lib/src/elf.cc --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libexec/lib/src/elf.cc Wed May 11 17:23:11 2022 +0200 @@ -0,0 +1,158 @@ +/* + * ELF payload decoding support. + * + * Copyright (C) 2022 Paul Boddie + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA + */ + +#include + +#include "elf.h" + + + +/* Generic segment creation from program segments. */ + +Segment *ProgramSegment::segment() +{ + return new Segment( + region_address(), + region_size(), + region_flags(), + file_offset(), + file_contents()); +} + + + +/* Program segment construction for 32- or 64-bit variants. */ + +template +ProgramSegmentVariant::ProgramSegmentVariant(PROGRAM_HEADER *header) +: _header(header) +{ +} + +template +bool ProgramSegmentVariant::loadable() +{ + return _header->p_type == PT_LOAD; +} + +template +offset_t ProgramSegmentVariant::file_contents() +{ + return _header->p_filesz; +} + +template +offset_t ProgramSegmentVariant::file_offset() +{ + return _header->p_offset; +} + +template +l4_addr_t ProgramSegmentVariant::region_address() +{ + return _header->p_vaddr; +} + +template +offset_t ProgramSegmentVariant::region_size() +{ + return _header->p_memsz; +} + +template +l4re_rm_flags_t ProgramSegmentVariant::region_flags() +{ + l4re_rm_flags_t flags = 0; + + if (_header->p_flags & PF_R) + flags |= L4RE_RM_F_R; + if (_header->p_flags & PF_W) + flags |= L4RE_RM_F_W; + if (_header->p_flags & PF_X) + flags |= L4RE_RM_F_X; + + return flags; +} + + + +/* ELF payload construction for 32- or 64-bit variants. */ + +template +PayloadVariant::PayloadVariant(HEADER *header) +: _header(header) +{ +} + +template +l4_addr_t PayloadVariant::entry_point() +{ + return _header->e_entry; +} + +template +offset_t PayloadVariant::header_extent() +{ + return sizeof(HEADER); +} + +template +offset_t PayloadVariant::program_header_extent() +{ + return _header->e_phoff + _header->e_phentsize * _header->e_phnum; +} + +template +unsigned int PayloadVariant::segments() +{ + return _header->e_phnum; +} + +template +ProgramSegment *PayloadVariant::segment(unsigned int i) +{ + if (i >= segments()) + return NULL; + + return new ProgramSegmentVariant( + (PROGRAM_HEADER *) ((char *) _header + _header->e_phoff + + _header->e_phentsize * i)); +} + + + +/* Return the appropriate payload object. */ + +Payload *get_payload(char *buf) +{ + switch (buf[EI_CLASS]) + { + case (char) 1: + return new PayloadVariant((Elf32_Ehdr *) buf); + case (char) 2: + return new PayloadVariant((Elf64_Ehdr *) buf); + default: + return NULL; + } +} + +/* vim: tabstop=2 expandtab shiftwidth=2 +*/ diff -r 224d34e52d85 -r 06b056cac249 tests/dstest_exec.cc --- a/tests/dstest_exec.cc Wed May 11 16:37:05 2022 +0200 +++ b/tests/dstest_exec.cc Wed May 11 17:23:11 2022 +0200 @@ -25,6 +25,7 @@ #include #include +#include #include #include #include @@ -275,153 +276,6 @@ -/* Generic program segment interface. */ - -class ProgramSegment -{ -public: - virtual bool loadable() = 0; - virtual offset_t file_contents() = 0; - virtual offset_t file_offset() = 0; - virtual l4_addr_t region_address() = 0; - virtual offset_t region_size() = 0; - virtual l4re_rm_flags_t region_flags() = 0; - - Segment *segment() - { - return new Segment( - region_address(), - region_size(), - region_flags(), - file_offset(), - file_contents()); - } -}; - -template -class ProgramSegmentVariant : public ProgramSegment -{ -protected: - PROGRAM_HEADER *_header; - -public: - explicit ProgramSegmentVariant(PROGRAM_HEADER *header) - : _header(header) - { - } - - bool loadable() - { - return _header->p_type == PT_LOAD; - } - - offset_t file_contents() - { - return _header->p_filesz; - } - - offset_t file_offset() - { - return _header->p_offset; - } - - l4_addr_t region_address() - { - return _header->p_vaddr; - } - - offset_t region_size() - { - return _header->p_memsz; - } - - l4re_rm_flags_t region_flags() - { - l4re_rm_flags_t flags = 0; - - if (_header->p_flags & PF_R) - flags |= L4RE_RM_F_R; - if (_header->p_flags & PF_W) - flags |= L4RE_RM_F_W; - if (_header->p_flags & PF_X) - flags |= L4RE_RM_F_X; - - return flags; - } -}; - - - -/* Generic interface for an ELF payload. */ - -class Payload -{ -public: - virtual l4_addr_t entry_point() = 0; - virtual offset_t header_extent() = 0; - virtual offset_t program_header_extent() = 0; - virtual unsigned int segments() = 0; - virtual ProgramSegment *segment(unsigned int i) = 0; -}; - -template -class PayloadVariant : public Payload -{ -protected: - HEADER *_header; - -public: - explicit PayloadVariant(HEADER *header) - : _header(header) - { - } - - l4_addr_t entry_point() - { - return _header->e_entry; - } - - offset_t header_extent() - { - return sizeof(HEADER); - } - - offset_t program_header_extent() - { - return _header->e_phoff + _header->e_phentsize * _header->e_phnum; - } - - unsigned int segments() - { - return _header->e_phnum; - } - - ProgramSegment *segment(unsigned int i) - { - if (i >= segments()) - return NULL; - - return new ProgramSegmentVariant( - (PROGRAM_HEADER *) ((char *) _header + _header->e_phoff + - _header->e_phentsize * i)); - } -}; - -static Payload *get_payload(char *buf) -{ - switch (buf[EI_CLASS]) - { - case (char) 1: - return new PayloadVariant((Elf32_Ehdr *) buf); - case (char) 2: - return new PayloadVariant((Elf64_Ehdr *) buf); - default: - return NULL; - } -} - - - static ExecPager exec_pager; static void init_pager(ipc_server_config_type *config)