1 /* 2 * Stack support for new tasks and threads. 3 * 4 * Copyright (C) 2022 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/util/elf.h> 23 #include <l4/util/util.h> 24 25 #include <l4/libloader/adjust_stack> 26 27 #include <mem/memory_utils.h> 28 29 #include <string.h> 30 31 #include "stack.h" 32 33 34 35 /* Initialise a stack in a memory segment. */ 36 37 Stack::Stack(Segment &segment) 38 : _segment(segment) 39 { 40 _element = (l4_umword_t *) (segment.address() + segment.size()); 41 } 42 43 /* Set any additional initial capabilities. */ 44 45 void Stack::set_init_caps(l4re_env_cap_entry_t *entries) 46 { 47 _cap_entries = entries; 48 } 49 50 /* Set any indicated memory regions. */ 51 52 void Stack::set_regions(struct exec_region *regions) 53 { 54 _region_entries = regions; 55 } 56 57 /* Push any indicated memory regions. */ 58 59 void Stack::push_regions() 60 { 61 struct exec_region *region = (struct exec_region *) _element; 62 struct exec_region *regions = _region_entries; 63 64 /* Terminate the regions with a null entry. */ 65 66 *(--region) = (struct exec_region) {0, 0, 0, L4_INVALID_CAP}; 67 68 for (; (regions != NULL) && (regions->ds != L4_INVALID_CAP); regions++) 69 { 70 *(--region) = *regions; 71 } 72 73 _regions = (l4_addr_t) region; 74 _element = (l4_umword_t *) region; 75 } 76 77 /* Push any additional initial capabilities. */ 78 79 void Stack::push_init_caps() 80 { 81 l4re_env_cap_entry_t *entry = (l4re_env_cap_entry_t *) _element; 82 l4re_env_cap_entry_t *entries = _cap_entries; 83 84 /* Terminate the capabilities with a null entry. */ 85 86 *(--entry) = l4re_env_cap_entry_t(); 87 88 for (; (entries != NULL) && (entries->flags != ~0UL); entries++) 89 { 90 *(--entry) = *entries; 91 _num_caps++; 92 } 93 94 _caps = (l4_addr_t) entry; 95 _element = (l4_umword_t *) entry; 96 } 97 98 /* Push environment values in reverse order. */ 99 100 void Stack::push_string(const char *s) 101 { 102 char *arg = (char *) _element; 103 char *arg_last = arg; 104 105 arg -= round(strlen(s) + 1, sizeof(l4_umword_t)); 106 107 memset(arg, 0, arg_last - arg); 108 memcpy(arg, s, strlen(s)); 109 110 _element = (l4_umword_t *) arg; 111 } 112 113 /* Push environment values in reverse order. */ 114 115 void Stack::push_env(const char *envp[]) 116 { 117 _env_top = (char *) _element; 118 _env_entries = 0; 119 120 for (; *envp != NULL; envp++, _env_entries++) 121 push_string(*envp); 122 } 123 124 /* Push argument values in reverse order. */ 125 126 void Stack::push_args(int argc, const char *argv[]) 127 { 128 _arg_top = (char *) _element; 129 130 for (int i = 0; i < argc; i++) 131 push_string(argv[i]); 132 } 133 134 /* Loader flags, debugging flags, and the KIP capability index. 135 See: generate_l4aux in Remote_app_model */ 136 137 void Stack::push_l4re_aux() 138 { 139 /* Regions for the region mapper. */ 140 141 if (_regions) 142 *(--_element) = _segment.region_address((char *) _regions); 143 else 144 *(--_element) = 0; 145 146 /* Reserve space for the actual L4Re auxiliary structure. */ 147 148 _aux = (l4re_aux_t *) _element; 149 _aux--; 150 _element = (l4_umword_t *) _aux; 151 } 152 153 void Stack::push_l4re_env() 154 { 155 _env = (l4re_env_t *) _element; 156 _env--; 157 _element = (l4_umword_t *) _env; 158 } 159 160 /* Set the common auxiliary information. */ 161 162 void Stack::set_l4re_aux(l4re_aux_t *aux) 163 { 164 memcpy(_aux, aux, sizeof(l4re_aux_t)); 165 166 /* Take the binary name from the first program argument. */ 167 168 _aux->binary = (char *) _argv[0]; 169 } 170 171 /* Set the common environment, introducing the reference to additional 172 capabilities. */ 173 174 void Stack::set_l4re_env(l4re_env_t *env) 175 { 176 memcpy(_env, env, sizeof(l4re_env_t)); 177 _env->caps = (l4re_env_cap_entry_t *) (_segment.region_address(_caps)); 178 } 179 180 /* Push the auxiliary vector. */ 181 182 void Stack::push_auxv() 183 { 184 _auxv_end = (char *) _element; 185 186 struct auxv_entry *auxv_base = (struct auxv_entry *) _element; 187 188 *(--auxv_base) = {AT_NULL, 0}; 189 190 /* L4Re global environment pointer. */ 191 192 *(--auxv_base) = {AT_L4_ENV, _segment.region_address((char *) _env)}; 193 194 /* L4Re auxiliary structure pointer. */ 195 196 *(--auxv_base) = {AT_L4_AUX, _segment.region_address((char *) _aux)}; 197 198 /* Apparently required entries. 199 NOTE: The user/group identifiers should be obtained from the broader 200 environment. */ 201 202 *(--auxv_base) = {AT_PAGESZ, L4_PAGESIZE}; 203 *(--auxv_base) = {AT_UID, 0}; 204 *(--auxv_base) = {AT_EUID, 0}; 205 *(--auxv_base) = {AT_GID, 0}; 206 *(--auxv_base) = {AT_EGID, 0}; 207 208 _element = (l4_umword_t *) auxv_base; 209 } 210 211 /* Fill the stack in reverse with an address, returning the size of the 212 value. */ 213 214 offset_t Stack::write_address(char *arg, char **addr, const char *s) 215 { 216 offset_t size = round(strlen(s) + 1, sizeof(l4_umword_t)); 217 218 *addr = (char *) _segment.region_address(arg - size); 219 return size; 220 } 221 222 /* Populate stack with environment pointers, employing a pointer ordering 223 that is the reverse of the value ordering. */ 224 225 void Stack::push_envp(const char *envp[]) 226 { 227 /* Write the terminating element. */ 228 229 *(--_element) = 0; 230 231 /* Reserve space and fill the stack from the top inwards. */ 232 233 char **ep = (char **) (_element - _env_entries); 234 char *arg = _env_top; 235 236 for (; *envp != NULL; envp++, ep++) 237 arg -= write_address(arg, ep, *envp); 238 239 _element -= _env_entries; 240 } 241 242 /* Populate stack with argument pointers and count, employing a pointer 243 ordering that is the reverse of the value ordering. */ 244 245 void Stack::push_argv(int argc, const char *argv[]) 246 { 247 /* Write the terminating element. */ 248 249 *(--_element) = 0; 250 251 /* Reserve space and fill the stack from the top inwards. */ 252 253 _argv = (char **) (_element - argc); 254 char *arg = _arg_top; 255 256 for (int i = 0; i < argc; i++) 257 arg -= write_address(arg, &_argv[i], argv[i]); 258 259 /* Write the count. */ 260 261 _element -= argc; 262 263 *(--_element) = argc; 264 } 265 266 /* Adjust the stack alignment and return the stack address. */ 267 268 l4_addr_t Stack::align_stack() 269 { 270 char *current = (char *) _element; 271 char *adjusted = Ldr::adjust_sp(current, NULL); 272 273 if (adjusted != current) 274 memmove(adjusted, (const void *) current, _auxv_end - current); 275 276 _element = (l4_umword_t *) adjusted; 277 278 return _segment.region_address(adjusted); 279 } 280 281 /* Populate the stack with arguments and initial environment. */ 282 283 void Stack::populate(int argc, const char *argv[], const char *envp[]) 284 { 285 /* Populate stack with any regions and capabilities. */ 286 287 push_regions(); 288 push_init_caps(); 289 290 /* Populate stack with environment and argument values. */ 291 292 push_env(envp); 293 push_args(argc, argv); 294 295 /* Push L4Re flags, environment and auxiliary vector. */ 296 297 push_l4re_aux(); 298 push_l4re_env(); 299 push_auxv(); 300 301 /* Push environment and argument pointers. */ 302 303 push_envp(envp); 304 push_argv(argc, argv); 305 306 /* Adjust the stack alignment, setting the start address. */ 307 308 _start = align_stack(); 309 } 310 311 /* Return the stack pointer start address in the mapped program segment. */ 312 313 l4_addr_t Stack::start_address() 314 { 315 return _start; 316 } 317 318 /* vim: tabstop=2 expandtab shiftwidth=2 319 */