L4Re/departure

libexec/lib/src/segment.cc

520:79622a75409c
19 months ago Paul Boddie Fixed file member initialisation.
     1 /*     2  * Program memory segment support.     3  *     4  * Copyright (C) 2022, 2023 Paul Boddie <paul@boddie.org.uk>     5  *     6  * This program is free software; you can redistribute it and/or     7  * modify it under the terms of the GNU General Public License as     8  * published by the Free Software Foundation; either version 2 of     9  * the License, or (at your option) any later version.    10  *    11  * This program is distributed in the hope that it will be useful,    12  * but WITHOUT ANY WARRANTY; without even the implied warranty of    13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the    14  * GNU General Public License for more details.    15  *    16  * You should have received a copy of the GNU General Public License    17  * along with this program; if not, write to the Free Software    18  * Foundation, Inc., 51 Franklin Street, Fifth Floor,    19  * Boston, MA  02110-1301, USA    20  */    21     22 #include <l4/sys/err.h>    23     24 #include <ipc/cap_alloc.h>    25 #include <ipc/mem_ipc.h>    26 #include <mem/memory_utils.h>    27     28 #include <stdio.h>    29 #include <string.h>    30     31 #include "segment.h"    32     33     34     35 /* Free the allocated resources. */    36     37 Segment::~Segment()    38 {    39   if (_allocated)    40   {    41     if (_attached)    42       ipc_detach_dataspace(_buf);    43     44     /* Also unmap the dataspace, not apparently done by the underlying    45        functions. */    46     47     if (l4_is_valid_cap(_ds))    48       ipc_cap_free_um(_ds);    49   }    50   else if (client_opened(_file))    51   {    52     client_close(_file);    53     _file = NULL;    54   }    55 }    56     57 /* Common initialisation. */    58     59 void Segment::init()    60 {    61   _region_base = trunc(region_address(), L4_PAGESIZE);    62   _region_content_offset = region_address() - _region_base;    63     64   /* Expand the region size. */    65     66   _region_allocated_size = round(region_size() + _region_content_offset, L4_PAGESIZE);    67 }    68     69 /* Return the capability of the dataspace providing the memory. */    70     71 l4_cap_idx_t Segment::cap()    72 {    73   return _ds;    74 }    75     76 /* Return the address of allocated memory. */    77     78 char *Segment::address()    79 {    80   return _buf;    81 }    82     83 /* Return the size of the allocated memory. */    84     85 offset_t Segment::size()    86 {    87   return _region_allocated_size;    88 }    89     90 /* Allocate a writable region for the segment. */    91     92 long Segment::allocate(bool attach)    93 {    94   _allocated = true;    95   _attached = attach;    96     97   if (attach)    98     return ipc_allocate_align(_region_allocated_size,    99                               L4RE_RM_F_SEARCH_ADDR | L4RE_RM_F_RW,   100                               L4_PAGESHIFT, (void **) &_buf, &_ds);   101   else   102     return ipc_new_dataspace(_region_allocated_size,   103                              L4RE_RM_F_SEARCH_ADDR | L4RE_RM_F_RW,   104                              L4_PAGESHIFT, &_ds);   105 }   106    107 /* Fill a segment region with file content. */   108    109 long Segment::fill(file_t *file, bool attach)   110 {   111   /* Provide the exposed file contents in a masked memory mapped region, or if   112      not attaching the region, merely request access via a dataspace. */   113    114   if (attach)   115   {   116     _buf = (char *) client_mmap(file,   117                                 file_offset() - _region_content_offset,   118                                 _region_allocated_size,   119                                 file_offset(),   120                                 file_offset() + file_contents(),   121                                 region_flags());   122     if (_buf == NULL)   123       return -L4_EIO;   124   }   125   else   126   {   127     long err = file_mmap_only(file,   128                               file_offset() - _region_content_offset,   129                               _region_allocated_size,   130                               file_offset(),   131                               file_offset() + file_contents());   132     if (err)   133       return err;   134   }   135    136   _file = file;   137   _ds = file->ref;   138   return L4_EOK;   139 }   140    141 /* Define and return the mapped region for the segment. */   142    143 MappedRegion &Segment::region()   144 {   145   _region = MappedRegion(_region_base, _region_base + _region_allocated_size,   146                          region_flags(), _ds, (l4_addr_t) _buf);   147   return _region;   148 }   149    150 /* Define and return the region dataspace details. */   151    152 struct exec_region &Segment::exec_region()   153 {   154   _exec_region = (struct exec_region) {_region_base, _region_allocated_size, region_flags(), _ds};   155   return _exec_region;   156 }   157    158 /* Return the mapped address corresponding to the given address. */   159    160 l4_addr_t Segment::region_address(char *address)   161 {   162   return (l4_addr_t) ((address - _buf) + (char *) _region_base);   163 }   164    165 l4_addr_t Segment::region_address(l4_addr_t address)   166 {   167   return (address - (l4_addr_t) _buf) + _region_base;   168 }   169    170    171    172 /* Initialise a memory segment using explicit parameters. */   173    174 ExplicitSegment::ExplicitSegment(l4_addr_t base, offset_t size,   175                                  l4re_rm_flags_t flags, offset_t file_offset,   176                                  offset_t file_contents)   177 : _base(base), _size(size), _flags(flags), _file_offset(file_offset),   178   _file_contents(file_contents)   179 {   180   init();   181 }   182    183 /* Return the amount of file content loaded into the segment. */   184    185 bool ExplicitSegment::loadable()   186 {   187   return false;   188 }   189    190 offset_t ExplicitSegment::file_contents()   191 {   192   return _file_contents;   193 }   194    195 offset_t ExplicitSegment::file_offset()   196 {   197   return _file_offset;   198 }   199    200 l4_addr_t ExplicitSegment::region_address()   201 {   202   return _base;   203 }   204    205 offset_t ExplicitSegment::region_size()   206 {   207   return _size;   208 }   209    210 /* Return the region flags for the segment. */   211    212 l4re_rm_flags_t ExplicitSegment::region_flags()   213 {   214   return _flags;   215 }   216    217 /* vim: tabstop=2 expandtab shiftwidth=2   218 */