1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/libexec/include/exec/elf.h Wed May 11 17:23:11 2022 +0200
1.3 @@ -0,0 +1,95 @@
1.4 +/*
1.5 + * ELF payload decoding support.
1.6 + *
1.7 + * Copyright (C) 2022 Paul Boddie <paul@boddie.org.uk>
1.8 + *
1.9 + * This program is free software; you can redistribute it and/or
1.10 + * modify it under the terms of the GNU General Public License as
1.11 + * published by the Free Software Foundation; either version 2 of
1.12 + * the License, or (at your option) any later version.
1.13 + *
1.14 + * This program is distributed in the hope that it will be useful,
1.15 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
1.16 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1.17 + * GNU General Public License for more details.
1.18 + *
1.19 + * You should have received a copy of the GNU General Public License
1.20 + * along with this program; if not, write to the Free Software
1.21 + * Foundation, Inc., 51 Franklin Street, Fifth Floor,
1.22 + * Boston, MA 02110-1301, USA
1.23 + */
1.24 +
1.25 +#include <exec/segment.h>
1.26 +
1.27 +
1.28 +
1.29 +/* Generic program segment interface. */
1.30 +
1.31 +class ProgramSegment
1.32 +{
1.33 +public:
1.34 + virtual bool loadable() = 0;
1.35 + virtual offset_t file_contents() = 0;
1.36 + virtual offset_t file_offset() = 0;
1.37 + virtual l4_addr_t region_address() = 0;
1.38 + virtual offset_t region_size() = 0;
1.39 + virtual l4re_rm_flags_t region_flags() = 0;
1.40 +
1.41 + Segment *segment();
1.42 +};
1.43 +
1.44 +template <typename PROGRAM_HEADER>
1.45 +class ProgramSegmentVariant : public ProgramSegment
1.46 +{
1.47 +protected:
1.48 + PROGRAM_HEADER *_header;
1.49 +
1.50 +public:
1.51 + explicit ProgramSegmentVariant(PROGRAM_HEADER *header);
1.52 +
1.53 + bool loadable();
1.54 + offset_t file_contents();
1.55 + offset_t file_offset();
1.56 + l4_addr_t region_address();
1.57 + offset_t region_size();
1.58 + l4re_rm_flags_t region_flags();
1.59 +};
1.60 +
1.61 +
1.62 +
1.63 +/* Generic interface for an ELF payload. */
1.64 +
1.65 +class Payload
1.66 +{
1.67 +public:
1.68 + virtual l4_addr_t entry_point() = 0;
1.69 + virtual offset_t header_extent() = 0;
1.70 + virtual offset_t program_header_extent() = 0;
1.71 + virtual unsigned int segments() = 0;
1.72 + virtual ProgramSegment *segment(unsigned int i) = 0;
1.73 +};
1.74 +
1.75 +template <typename HEADER, typename PROGRAM_HEADER>
1.76 +class PayloadVariant : public Payload
1.77 +{
1.78 +protected:
1.79 + HEADER *_header;
1.80 +
1.81 +public:
1.82 + explicit PayloadVariant(HEADER *header);
1.83 +
1.84 + l4_addr_t entry_point();
1.85 + offset_t header_extent();
1.86 + offset_t program_header_extent();
1.87 + unsigned int segments();
1.88 + ProgramSegment *segment(unsigned int i);
1.89 +};
1.90 +
1.91 +
1.92 +
1.93 +/* Return the appropriate payload object. */
1.94 +
1.95 +Payload *get_payload(char *buf);
1.96 +
1.97 +/* vim: tabstop=2 expandtab shiftwidth=2
1.98 +*/
2.1 --- a/libexec/lib/src/Makefile Wed May 11 16:37:05 2022 +0200
2.2 +++ b/libexec/lib/src/Makefile Wed May 11 17:23:11 2022 +0200
2.3 @@ -3,7 +3,7 @@
2.4
2.5 TARGET = libexec.a libexec.so
2.6 PC_FILENAME = libexec
2.7 -SRC_CC = process.cc segment.cc stack.cc
2.8 +SRC_CC = elf.cc process.cc segment.cc stack.cc
2.9 REQUIRES_LIBS = l4re_c-util libmem libipc libstdc++ libsystypes libfsclient
2.10
2.11 PRIVATE_INCDIR += $(PKGDIR)/include/exec
3.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
3.2 +++ b/libexec/lib/src/elf.cc Wed May 11 17:23:11 2022 +0200
3.3 @@ -0,0 +1,158 @@
3.4 +/*
3.5 + * ELF payload decoding support.
3.6 + *
3.7 + * Copyright (C) 2022 Paul Boddie <paul@boddie.org.uk>
3.8 + *
3.9 + * This program is free software; you can redistribute it and/or
3.10 + * modify it under the terms of the GNU General Public License as
3.11 + * published by the Free Software Foundation; either version 2 of
3.12 + * the License, or (at your option) any later version.
3.13 + *
3.14 + * This program is distributed in the hope that it will be useful,
3.15 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
3.16 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
3.17 + * GNU General Public License for more details.
3.18 + *
3.19 + * You should have received a copy of the GNU General Public License
3.20 + * along with this program; if not, write to the Free Software
3.21 + * Foundation, Inc., 51 Franklin Street, Fifth Floor,
3.22 + * Boston, MA 02110-1301, USA
3.23 + */
3.24 +
3.25 +#include <l4/util/elf.h>
3.26 +
3.27 +#include "elf.h"
3.28 +
3.29 +
3.30 +
3.31 +/* Generic segment creation from program segments. */
3.32 +
3.33 +Segment *ProgramSegment::segment()
3.34 +{
3.35 + return new Segment(
3.36 + region_address(),
3.37 + region_size(),
3.38 + region_flags(),
3.39 + file_offset(),
3.40 + file_contents());
3.41 +}
3.42 +
3.43 +
3.44 +
3.45 +/* Program segment construction for 32- or 64-bit variants. */
3.46 +
3.47 +template <typename PROGRAM_HEADER>
3.48 +ProgramSegmentVariant<PROGRAM_HEADER>::ProgramSegmentVariant(PROGRAM_HEADER *header)
3.49 +: _header(header)
3.50 +{
3.51 +}
3.52 +
3.53 +template <typename PROGRAM_HEADER>
3.54 +bool ProgramSegmentVariant<PROGRAM_HEADER>::loadable()
3.55 +{
3.56 + return _header->p_type == PT_LOAD;
3.57 +}
3.58 +
3.59 +template <typename PROGRAM_HEADER>
3.60 +offset_t ProgramSegmentVariant<PROGRAM_HEADER>::file_contents()
3.61 +{
3.62 + return _header->p_filesz;
3.63 +}
3.64 +
3.65 +template <typename PROGRAM_HEADER>
3.66 +offset_t ProgramSegmentVariant<PROGRAM_HEADER>::file_offset()
3.67 +{
3.68 + return _header->p_offset;
3.69 +}
3.70 +
3.71 +template <typename PROGRAM_HEADER>
3.72 +l4_addr_t ProgramSegmentVariant<PROGRAM_HEADER>::region_address()
3.73 +{
3.74 + return _header->p_vaddr;
3.75 +}
3.76 +
3.77 +template <typename PROGRAM_HEADER>
3.78 +offset_t ProgramSegmentVariant<PROGRAM_HEADER>::region_size()
3.79 +{
3.80 + return _header->p_memsz;
3.81 +}
3.82 +
3.83 +template <typename PROGRAM_HEADER>
3.84 +l4re_rm_flags_t ProgramSegmentVariant<PROGRAM_HEADER>::region_flags()
3.85 +{
3.86 + l4re_rm_flags_t flags = 0;
3.87 +
3.88 + if (_header->p_flags & PF_R)
3.89 + flags |= L4RE_RM_F_R;
3.90 + if (_header->p_flags & PF_W)
3.91 + flags |= L4RE_RM_F_W;
3.92 + if (_header->p_flags & PF_X)
3.93 + flags |= L4RE_RM_F_X;
3.94 +
3.95 + return flags;
3.96 +}
3.97 +
3.98 +
3.99 +
3.100 +/* ELF payload construction for 32- or 64-bit variants. */
3.101 +
3.102 +template <typename HEADER, typename PROGRAM_HEADER>
3.103 +PayloadVariant<HEADER, PROGRAM_HEADER>::PayloadVariant(HEADER *header)
3.104 +: _header(header)
3.105 +{
3.106 +}
3.107 +
3.108 +template <typename HEADER, typename PROGRAM_HEADER>
3.109 +l4_addr_t PayloadVariant<HEADER, PROGRAM_HEADER>::entry_point()
3.110 +{
3.111 + return _header->e_entry;
3.112 +}
3.113 +
3.114 +template <typename HEADER, typename PROGRAM_HEADER>
3.115 +offset_t PayloadVariant<HEADER, PROGRAM_HEADER>::header_extent()
3.116 +{
3.117 + return sizeof(HEADER);
3.118 +}
3.119 +
3.120 +template <typename HEADER, typename PROGRAM_HEADER>
3.121 +offset_t PayloadVariant<HEADER, PROGRAM_HEADER>::program_header_extent()
3.122 +{
3.123 + return _header->e_phoff + _header->e_phentsize * _header->e_phnum;
3.124 +}
3.125 +
3.126 +template <typename HEADER, typename PROGRAM_HEADER>
3.127 +unsigned int PayloadVariant<HEADER, PROGRAM_HEADER>::segments()
3.128 +{
3.129 + return _header->e_phnum;
3.130 +}
3.131 +
3.132 +template <typename HEADER, typename PROGRAM_HEADER>
3.133 +ProgramSegment *PayloadVariant<HEADER, PROGRAM_HEADER>::segment(unsigned int i)
3.134 +{
3.135 + if (i >= segments())
3.136 + return NULL;
3.137 +
3.138 + return new ProgramSegmentVariant<PROGRAM_HEADER>(
3.139 + (PROGRAM_HEADER *) ((char *) _header + _header->e_phoff +
3.140 + _header->e_phentsize * i));
3.141 +}
3.142 +
3.143 +
3.144 +
3.145 +/* Return the appropriate payload object. */
3.146 +
3.147 +Payload *get_payload(char *buf)
3.148 +{
3.149 + switch (buf[EI_CLASS])
3.150 + {
3.151 + case (char) 1:
3.152 + return new PayloadVariant<Elf32_Ehdr, Elf32_Phdr>((Elf32_Ehdr *) buf);
3.153 + case (char) 2:
3.154 + return new PayloadVariant<Elf64_Ehdr, Elf64_Phdr>((Elf64_Ehdr *) buf);
3.155 + default:
3.156 + return NULL;
3.157 + }
3.158 +}
3.159 +
3.160 +/* vim: tabstop=2 expandtab shiftwidth=2
3.161 +*/
4.1 --- a/tests/dstest_exec.cc Wed May 11 16:37:05 2022 +0200
4.2 +++ b/tests/dstest_exec.cc Wed May 11 17:23:11 2022 +0200
4.3 @@ -25,6 +25,7 @@
4.4 #include <l4/util/elf.h>
4.5 #include <l4/util/util.h>
4.6
4.7 +#include <exec/elf.h>
4.8 #include <exec/process.h>
4.9 #include <fsclient/client.h>
4.10 #include <ipc/mem_ipc.h>
4.11 @@ -275,153 +276,6 @@
4.12
4.13
4.14
4.15 -/* Generic program segment interface. */
4.16 -
4.17 -class ProgramSegment
4.18 -{
4.19 -public:
4.20 - virtual bool loadable() = 0;
4.21 - virtual offset_t file_contents() = 0;
4.22 - virtual offset_t file_offset() = 0;
4.23 - virtual l4_addr_t region_address() = 0;
4.24 - virtual offset_t region_size() = 0;
4.25 - virtual l4re_rm_flags_t region_flags() = 0;
4.26 -
4.27 - Segment *segment()
4.28 - {
4.29 - return new Segment(
4.30 - region_address(),
4.31 - region_size(),
4.32 - region_flags(),
4.33 - file_offset(),
4.34 - file_contents());
4.35 - }
4.36 -};
4.37 -
4.38 -template <typename PROGRAM_HEADER>
4.39 -class ProgramSegmentVariant : public ProgramSegment
4.40 -{
4.41 -protected:
4.42 - PROGRAM_HEADER *_header;
4.43 -
4.44 -public:
4.45 - explicit ProgramSegmentVariant(PROGRAM_HEADER *header)
4.46 - : _header(header)
4.47 - {
4.48 - }
4.49 -
4.50 - bool loadable()
4.51 - {
4.52 - return _header->p_type == PT_LOAD;
4.53 - }
4.54 -
4.55 - offset_t file_contents()
4.56 - {
4.57 - return _header->p_filesz;
4.58 - }
4.59 -
4.60 - offset_t file_offset()
4.61 - {
4.62 - return _header->p_offset;
4.63 - }
4.64 -
4.65 - l4_addr_t region_address()
4.66 - {
4.67 - return _header->p_vaddr;
4.68 - }
4.69 -
4.70 - offset_t region_size()
4.71 - {
4.72 - return _header->p_memsz;
4.73 - }
4.74 -
4.75 - l4re_rm_flags_t region_flags()
4.76 - {
4.77 - l4re_rm_flags_t flags = 0;
4.78 -
4.79 - if (_header->p_flags & PF_R)
4.80 - flags |= L4RE_RM_F_R;
4.81 - if (_header->p_flags & PF_W)
4.82 - flags |= L4RE_RM_F_W;
4.83 - if (_header->p_flags & PF_X)
4.84 - flags |= L4RE_RM_F_X;
4.85 -
4.86 - return flags;
4.87 - }
4.88 -};
4.89 -
4.90 -
4.91 -
4.92 -/* Generic interface for an ELF payload. */
4.93 -
4.94 -class Payload
4.95 -{
4.96 -public:
4.97 - virtual l4_addr_t entry_point() = 0;
4.98 - virtual offset_t header_extent() = 0;
4.99 - virtual offset_t program_header_extent() = 0;
4.100 - virtual unsigned int segments() = 0;
4.101 - virtual ProgramSegment *segment(unsigned int i) = 0;
4.102 -};
4.103 -
4.104 -template <typename HEADER, typename PROGRAM_HEADER>
4.105 -class PayloadVariant : public Payload
4.106 -{
4.107 -protected:
4.108 - HEADER *_header;
4.109 -
4.110 -public:
4.111 - explicit PayloadVariant(HEADER *header)
4.112 - : _header(header)
4.113 - {
4.114 - }
4.115 -
4.116 - l4_addr_t entry_point()
4.117 - {
4.118 - return _header->e_entry;
4.119 - }
4.120 -
4.121 - offset_t header_extent()
4.122 - {
4.123 - return sizeof(HEADER);
4.124 - }
4.125 -
4.126 - offset_t program_header_extent()
4.127 - {
4.128 - return _header->e_phoff + _header->e_phentsize * _header->e_phnum;
4.129 - }
4.130 -
4.131 - unsigned int segments()
4.132 - {
4.133 - return _header->e_phnum;
4.134 - }
4.135 -
4.136 - ProgramSegment *segment(unsigned int i)
4.137 - {
4.138 - if (i >= segments())
4.139 - return NULL;
4.140 -
4.141 - return new ProgramSegmentVariant<PROGRAM_HEADER>(
4.142 - (PROGRAM_HEADER *) ((char *) _header + _header->e_phoff +
4.143 - _header->e_phentsize * i));
4.144 - }
4.145 -};
4.146 -
4.147 -static Payload *get_payload(char *buf)
4.148 -{
4.149 - switch (buf[EI_CLASS])
4.150 - {
4.151 - case (char) 1:
4.152 - return new PayloadVariant<Elf32_Ehdr, Elf32_Phdr>((Elf32_Ehdr *) buf);
4.153 - case (char) 2:
4.154 - return new PayloadVariant<Elf64_Ehdr, Elf64_Phdr>((Elf64_Ehdr *) buf);
4.155 - default:
4.156 - return NULL;
4.157 - }
4.158 -}
4.159 -
4.160 -
4.161 -
4.162 static ExecPager exec_pager;
4.163
4.164 static void init_pager(ipc_server_config_type *config)