diff options
| author | Po Lu | 2023-04-30 21:37:19 +0800 |
|---|---|---|
| committer | Po Lu | 2023-04-30 21:37:19 +0800 |
| commit | 368f6f3942a1f8b9483763a6ac24b3b3021e92bf (patch) | |
| tree | 284ff92e18076ed7a8be3d2775ee450922b3166d /exec/exec.c | |
| parent | 4289ed6cffdb5ea758a78037fe385fd7c4e23677 (diff) | |
| download | emacs-368f6f3942a1f8b9483763a6ac24b3b3021e92bf.tar.gz emacs-368f6f3942a1f8b9483763a6ac24b3b3021e92bf.zip | |
Add helper binary `exec1'
* .gitignore: New files.
* Makefile.in (mostlyclean_dirs): Add libexec, if its Makefile
exists.
* autogen.sh (do_git): Autoreconf in exec as well.
* configure.ac: Configure libexec on Android.
* exec/Makefile.in:
* exec/README:
* exec/config-mips.m4.in:
* exec/config.guess:
* exec/config.h.in:
* exec/config.sub:
* exec/configure:
* exec/configure.ac:
* exec/deps.mk:
* exec/exec.c (MIN, struct exec_open_command)
(struct exec_map_command, struct exec_jump_command)
(write_open_command, write_load_command, process_interpreter_1)
(process_interpreter, process_program_header, insert_args)
(exec_0):
* exec/exec.h (_EXEC_H_, struct elf_header_32)
(struct program_header_32, struct dt_entry_32)
(struct elf_header_64, struct program_header_64)
(struct dt_entry_64, struct exec_tracee):
* exec/exec1.c (main):
* exec/install-sh (scriptversion):
* exec/loader-aarch64.s (_start):
* exec/loader-armeabi.s (_start):
* exec/loader-mips64el.s (__start):
* exec/loader-mipsel.s (__start):
* exec/loader-x86.s (_start):
* exec/loader-x86_64.s (_start):
* exec/mipsel-user.h (_MIPSEL_USER_H_):
* exec/mipsfpu.c (MIPS_ABI_FP_ANY, fpu_reqs, valid_abi_p)
(fp_mode_for_abi, cpu_supports_fr0_p, determine_fpu_mode):
* exec/mipsfpu.h (_MIPSFPU_H_, FP_FR0):
* exec/test.c (print_usage, main):
* exec/trace.c (MAX_TRACEES, aarch64_set_regs, read_memory)
(user_alloca, user_copy, remove_tracee, handle_clone)
(syscall_trap_p, handle_exec, process_system_call, tracing_execve)
(after_fork, find_tracee, exec_waitpid, exec_init): New files.
* java/Makefile.in (CROSS_EXEC_BINS): Add exec1 and
loader.
($(CROSS_EXEC_BINS) &): New target.
Diffstat (limited to 'exec/exec.c')
| -rw-r--r-- | exec/exec.c | 1016 |
1 files changed, 1016 insertions, 0 deletions
diff --git a/exec/exec.c b/exec/exec.c new file mode 100644 index 00000000000..e890179a9ab --- /dev/null +++ b/exec/exec.c | |||
| @@ -0,0 +1,1016 @@ | |||
| 1 | /* Program execution for Emacs. | ||
| 2 | |||
| 3 | Copyright (C) 2023 Free Software Foundation, Inc. | ||
| 4 | |||
| 5 | This file is part of GNU Emacs. | ||
| 6 | |||
| 7 | GNU Emacs is free software: you can redistribute it and/or modify | ||
| 8 | it under the terms of the GNU General Public License as published by | ||
| 9 | the Free Software Foundation, either version 3 of the License, or (at | ||
| 10 | your option) any later version. | ||
| 11 | |||
| 12 | GNU Emacs is distributed in the hope that it will be useful, | ||
| 13 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 15 | GNU General Public License for more details. | ||
| 16 | |||
| 17 | You should have received a copy of the GNU General Public License | ||
| 18 | along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */ | ||
| 19 | |||
| 20 | #include <config.h> | ||
| 21 | |||
| 22 | #include <errno.h> | ||
| 23 | #include <unistd.h> | ||
| 24 | #include <string.h> | ||
| 25 | #include <fcntl.h> | ||
| 26 | #include <assert.h> | ||
| 27 | #include <string.h> | ||
| 28 | #include <ctype.h> | ||
| 29 | |||
| 30 | #include <sys/ptrace.h> | ||
| 31 | #include <sys/param.h> | ||
| 32 | #include <sys/mman.h> | ||
| 33 | |||
| 34 | #ifndef MIN | ||
| 35 | #define MIN(a, b) ((a) < (b) ? (a) : (b)) | ||
| 36 | #endif /* MIN */ | ||
| 37 | |||
| 38 | #ifndef MAX | ||
| 39 | #define MAX(a, b) ((a) < (b) ? (b) : (a)) | ||
| 40 | #endif /* MAX */ | ||
| 41 | |||
| 42 | #include "exec.h" | ||
| 43 | |||
| 44 | #if defined __mips__ && !defined MIPS_NABI | ||
| 45 | #include "mipsfpu.h" | ||
| 46 | #endif /* defined __mips__ && !defined MIPS_NABI */ | ||
| 47 | |||
| 48 | |||
| 49 | |||
| 50 | /* Executable reading functions. | ||
| 51 | These functions extract information from an executable that is | ||
| 52 | about to be loaded. | ||
| 53 | |||
| 54 | `exec_0' takes the name of the program, determines whether or not | ||
| 55 | its format is correct, and if so, returns the list of actions that | ||
| 56 | the loader should perform. | ||
| 57 | |||
| 58 | The actions include: | ||
| 59 | |||
| 60 | - Making the stack executable, if PT_GNU_STACK. | ||
| 61 | - Mapping PT_LOAD sections into the executable with the correct | ||
| 62 | memory protection. | ||
| 63 | - On MIPS, setting the floating point register size. | ||
| 64 | - Transferring control to the interpreter or executable. */ | ||
| 65 | |||
| 66 | |||
| 67 | /* Check whether or not FD starts with a #!, and return the executable | ||
| 68 | to load if it does. Value is NAME if no interpreter character was | ||
| 69 | found, or the interpreter otherwise. Value is NULL upon an IO | ||
| 70 | error. | ||
| 71 | |||
| 72 | If an additional command line argument is specified, place it in | ||
| 73 | *EXTRA. */ | ||
| 74 | |||
| 75 | static const char * | ||
| 76 | check_interpreter (const char *name, int fd, const char **extra) | ||
| 77 | { | ||
| 78 | static char buffer[PATH_MAX], *start; | ||
| 79 | char first[2], *end, *ws; | ||
| 80 | ssize_t rc; | ||
| 81 | |||
| 82 | /* Read the first character. */ | ||
| 83 | rc = read (fd, &first, 2); | ||
| 84 | |||
| 85 | if (rc != 2) | ||
| 86 | goto fail; | ||
| 87 | |||
| 88 | if (first[0] != '#' || first[1] != '!') | ||
| 89 | goto nomatch; | ||
| 90 | |||
| 91 | rc = read (fd, buffer, PATH_MAX); | ||
| 92 | |||
| 93 | if (rc < 0) | ||
| 94 | goto fail; | ||
| 95 | |||
| 96 | /* Strip leading whitespace. */ | ||
| 97 | start = buffer; | ||
| 98 | while (*start && *start < 128 && isspace (*start)) | ||
| 99 | ++start; | ||
| 100 | |||
| 101 | /* Look for a newline character. */ | ||
| 102 | end = memchr (start, '\n', rc); | ||
| 103 | |||
| 104 | if (!end) | ||
| 105 | goto fail; | ||
| 106 | |||
| 107 | /* The string containing the interpreter is now in start. NULL | ||
| 108 | terminate it. */ | ||
| 109 | *end = '\0'; | ||
| 110 | |||
| 111 | /* Now look for any whitespace characters. */ | ||
| 112 | ws = strchr (start, ' '); | ||
| 113 | |||
| 114 | /* If there's no whitespace, return the entire start. */ | ||
| 115 | |||
| 116 | if (!ws) | ||
| 117 | { | ||
| 118 | if (lseek (fd, 0, SEEK_SET)) | ||
| 119 | goto fail; | ||
| 120 | |||
| 121 | return start; | ||
| 122 | } | ||
| 123 | |||
| 124 | /* Otherwise, split the string at the whitespace and return the | ||
| 125 | additional argument. */ | ||
| 126 | *ws = '\0'; | ||
| 127 | |||
| 128 | if (lseek (fd, 0, SEEK_SET)) | ||
| 129 | goto fail; | ||
| 130 | |||
| 131 | *extra = ws + 1; | ||
| 132 | return start; | ||
| 133 | |||
| 134 | nomatch: | ||
| 135 | /* There's no interpreter. */ | ||
| 136 | if (lseek (fd, 0, SEEK_SET)) | ||
| 137 | goto fail; | ||
| 138 | |||
| 139 | return name; | ||
| 140 | |||
| 141 | fail: | ||
| 142 | errno = ENOEXEC; | ||
| 143 | return NULL; | ||
| 144 | } | ||
| 145 | |||
| 146 | /* Static area used to store data placed on the loader's stack. */ | ||
| 147 | static char loader_area[65536]; | ||
| 148 | |||
| 149 | /* Number of bytes used in that area. */ | ||
| 150 | static int loader_area_used; | ||
| 151 | |||
| 152 | |||
| 153 | |||
| 154 | /* Structure definitions for commands placed in the loader area. | ||
| 155 | Arrange these so that each member is naturally aligned. */ | ||
| 156 | |||
| 157 | struct exec_open_command | ||
| 158 | { | ||
| 159 | /* Word identifying the type of this command. */ | ||
| 160 | USER_WORD command; | ||
| 161 | |||
| 162 | /* NULL-terminated file name follows, padded to the size of a user | ||
| 163 | word. */ | ||
| 164 | }; | ||
| 165 | |||
| 166 | struct exec_map_command | ||
| 167 | { | ||
| 168 | /* Word identifying the type of this command. */ | ||
| 169 | USER_WORD command; | ||
| 170 | |||
| 171 | /* Where the file will be mapped. */ | ||
| 172 | USER_WORD vm_address; | ||
| 173 | |||
| 174 | /* Offset into the file to map from. */ | ||
| 175 | USER_WORD file_offset; | ||
| 176 | |||
| 177 | /* Memory protection for mprotect. */ | ||
| 178 | USER_WORD protection; | ||
| 179 | |||
| 180 | /* Number of bytes to be mapped. */ | ||
| 181 | USER_WORD length; | ||
| 182 | |||
| 183 | /* Flags for mmap. */ | ||
| 184 | USER_WORD flags; | ||
| 185 | |||
| 186 | /* Number of bytes to clear at the end of this mapping. */ | ||
| 187 | USER_WORD clear; | ||
| 188 | }; | ||
| 189 | |||
| 190 | struct exec_jump_command | ||
| 191 | { | ||
| 192 | /* Word identifying the type of this command. */ | ||
| 193 | USER_WORD command; | ||
| 194 | |||
| 195 | /* Address to jump to. */ | ||
| 196 | USER_WORD entry; | ||
| 197 | |||
| 198 | /* The value of AT_ENTRY inside the aux vector. */ | ||
| 199 | USER_WORD at_entry; | ||
| 200 | |||
| 201 | /* The value of AT_PHENT inside the aux vector. */ | ||
| 202 | USER_WORD at_phent; | ||
| 203 | |||
| 204 | /* The value of AT_PHNUM inside the aux vector. */ | ||
| 205 | USER_WORD at_phnum; | ||
| 206 | |||
| 207 | /* The value of AT_PHDR inside the aux vector. */ | ||
| 208 | USER_WORD at_phdr; | ||
| 209 | |||
| 210 | /* The value of AT_BASE inside the aux vector. */ | ||
| 211 | USER_WORD at_base; | ||
| 212 | |||
| 213 | #if defined __mips__ && !defined MIPS_NABI | ||
| 214 | /* The FPU mode to apply. */ | ||
| 215 | USER_WORD fpu_mode; | ||
| 216 | #endif /* defined __mips__ && !defined MIPS_NABI */ | ||
| 217 | }; | ||
| 218 | |||
| 219 | |||
| 220 | |||
| 221 | /* Write a command to open the file NAME to the loader area. | ||
| 222 | If ALTERNATE is true, then use the command code 16 instead | ||
| 223 | of 0. Value is 1 upon failure, else 0. */ | ||
| 224 | |||
| 225 | static int | ||
| 226 | write_open_command (const char *name, bool alternate) | ||
| 227 | { | ||
| 228 | struct exec_open_command command; | ||
| 229 | size_t size; | ||
| 230 | |||
| 231 | /* First, write the command to open NAME. This is followed by NAME | ||
| 232 | itself, padded to sizeof (USER_WORD) bytes. */ | ||
| 233 | |||
| 234 | command.command = alternate ? 16 : 0; | ||
| 235 | if (sizeof loader_area - loader_area_used < sizeof command) | ||
| 236 | return 1; | ||
| 237 | memcpy (loader_area + loader_area_used, &command, sizeof command); | ||
| 238 | loader_area_used += sizeof command; | ||
| 239 | |||
| 240 | /* Calculate the length of NAME. */ | ||
| 241 | size = strlen (name) + 1; | ||
| 242 | |||
| 243 | /* Round it up. */ | ||
| 244 | size = ((size + (sizeof (USER_WORD) - 1)) | ||
| 245 | & ~(sizeof (USER_WORD) - 1)); | ||
| 246 | |||
| 247 | if (sizeof loader_area - loader_area_used < size) | ||
| 248 | return 1; | ||
| 249 | |||
| 250 | /* Now copy name to the loader area, filling the padding with NULL | ||
| 251 | bytes. */ | ||
| 252 | strncpy (loader_area + loader_area_used, name, size); | ||
| 253 | |||
| 254 | /* Increase loader_area_used. */ | ||
| 255 | loader_area_used += size; | ||
| 256 | return 0; | ||
| 257 | } | ||
| 258 | |||
| 259 | /* Write the commands necessary to map the executable file into memory | ||
| 260 | for the given PT_LOAD program HEADER. Value is 1 upon failure, | ||
| 261 | else 0. If USE_ALTERNATE, use the command code 17 instead of | ||
| 262 | 1. | ||
| 263 | |||
| 264 | Apply the given OFFSET to virtual addresses that will be mapped. */ | ||
| 265 | |||
| 266 | static int | ||
| 267 | write_load_command (program_header *header, bool use_alternate, | ||
| 268 | USER_WORD offset) | ||
| 269 | { | ||
| 270 | struct exec_map_command command; | ||
| 271 | struct exec_map_command command1; | ||
| 272 | USER_WORD start, end; | ||
| 273 | bool need_command1; | ||
| 274 | static long pagesize; | ||
| 275 | |||
| 276 | /* First, write the commands necessary to map the specified segment | ||
| 277 | itself. | ||
| 278 | |||
| 279 | This is the area between header->p_vaddr and header->p_filesz, | ||
| 280 | rounded up to the page size. */ | ||
| 281 | |||
| 282 | #ifndef PAGE_MASK | ||
| 283 | /* This system doesn't define a fixed page size. */ | ||
| 284 | |||
| 285 | #ifdef HAVE_GETPAGESIZE | ||
| 286 | if (!pagesize) | ||
| 287 | pagesize = getpagesize (); | ||
| 288 | #else /* HAVE_GETPAGESIZE */ | ||
| 289 | if (!pagesize) | ||
| 290 | pagesize = sysconf (_SC_PAGESIZE); | ||
| 291 | |||
| 292 | #define PAGE_MASK (~(pagesize - 1)) | ||
| 293 | #define PAGE_SIZE (pagesize) | ||
| 294 | #endif /* HAVE_GETPAGESIZE */ | ||
| 295 | #endif /* PAGE_MASK */ | ||
| 296 | |||
| 297 | start = header->p_vaddr & PAGE_MASK; | ||
| 298 | end = ((header->p_vaddr + header->p_filesz | ||
| 299 | + PAGE_SIZE) | ||
| 300 | & PAGE_MASK); | ||
| 301 | |||
| 302 | command.command = use_alternate ? 17 : 1; | ||
| 303 | command.vm_address = start; | ||
| 304 | command.file_offset = header->p_offset & PAGE_MASK; | ||
| 305 | command.protection = 0; | ||
| 306 | command.length = end - start; | ||
| 307 | command.clear = 0; | ||
| 308 | command.flags = MAP_PRIVATE | MAP_FIXED; | ||
| 309 | |||
| 310 | /* Apply the memory protection specified in the header. */ | ||
| 311 | |||
| 312 | if (header->p_flags & 4) /* PF_R */ | ||
| 313 | command.protection |= PROT_READ; | ||
| 314 | |||
| 315 | if (header->p_flags & 2) /* PF_W */ | ||
| 316 | command.protection |= PROT_WRITE; | ||
| 317 | |||
| 318 | if (header->p_flags & 1) /* PF_X */ | ||
| 319 | command.protection |= PROT_EXEC; | ||
| 320 | |||
| 321 | /* Next, write any command necessary to map pages in the area | ||
| 322 | between p_filesz and p_memsz. */ | ||
| 323 | need_command1 = false; | ||
| 324 | |||
| 325 | if (header->p_memsz > header->p_filesz) | ||
| 326 | { | ||
| 327 | /* If there are bytes after end which need to be initialized, do | ||
| 328 | that now. */ | ||
| 329 | command.clear = end - header->p_vaddr - header->p_filesz; | ||
| 330 | start = end; | ||
| 331 | end = header->p_vaddr + header->p_memsz + PAGE_SIZE; | ||
| 332 | end &= PAGE_MASK; | ||
| 333 | |||
| 334 | if (end > start) | ||
| 335 | { | ||
| 336 | command1.command = 4; | ||
| 337 | command1.vm_address = start; | ||
| 338 | command1.file_offset = 0; | ||
| 339 | command1.length = end - start; | ||
| 340 | command1.clear = 0; | ||
| 341 | command1.protection = command.protection; | ||
| 342 | command1.flags = MAP_PRIVATE | MAP_ANONYMOUS | MAP_FIXED; | ||
| 343 | need_command1 = true; | ||
| 344 | } | ||
| 345 | } | ||
| 346 | |||
| 347 | /* Apply the offset to both commands if necessary. */ | ||
| 348 | |||
| 349 | if (offset) | ||
| 350 | { | ||
| 351 | if (need_command1) | ||
| 352 | command1.vm_address += offset; | ||
| 353 | |||
| 354 | command.vm_address += offset; | ||
| 355 | } | ||
| 356 | |||
| 357 | /* Write both commands. */ | ||
| 358 | |||
| 359 | if (sizeof loader_area - loader_area_used < sizeof command) | ||
| 360 | return 1; | ||
| 361 | |||
| 362 | memcpy (loader_area + loader_area_used, &command, | ||
| 363 | sizeof command); | ||
| 364 | loader_area_used += sizeof command; | ||
| 365 | |||
| 366 | if (!need_command1) | ||
| 367 | return 0; | ||
| 368 | |||
| 369 | if (sizeof loader_area - loader_area_used < sizeof command1) | ||
| 370 | return 1; | ||
| 371 | |||
| 372 | memcpy (loader_area + loader_area_used, &command1, | ||
| 373 | sizeof command1); | ||
| 374 | loader_area_used += sizeof command1; | ||
| 375 | |||
| 376 | return 0; | ||
| 377 | } | ||
| 378 | |||
| 379 | #if defined __mips__ && !defined MIPS_NABI | ||
| 380 | |||
| 381 | /* Static storage used for MIPS ABI flags. */ | ||
| 382 | static struct mips_elf_abi_flags exec_abi, interpreter_abi; | ||
| 383 | |||
| 384 | /* Static storage for interpreter headers. */ | ||
| 385 | static elf_header exec_interpreter_header; | ||
| 386 | |||
| 387 | /* Pointer to the ELF header of this executable's interpreter. */ | ||
| 388 | static elf_header *interpreter_header; | ||
| 389 | |||
| 390 | /* Pointer to any PT_MIPS_ABIFLAGS program header found in the | ||
| 391 | executable itself. */ | ||
| 392 | static struct mips_elf_abi_flags *exec_abiflags; | ||
| 393 | |||
| 394 | /* Pointer to any PT_MIPS_ABIFLAGS program header found in the | ||
| 395 | executable's ELF interpreter. */ | ||
| 396 | static struct mips_elf_abi_flags *interpreter_abiflags; | ||
| 397 | |||
| 398 | #endif /* defined __mips__ && !defined MIPS_NABI */ | ||
| 399 | |||
| 400 | /* Process the specified program HEADER; HEADER is from the ELF | ||
| 401 | interpreter of another executable. FD is the executable file from | ||
| 402 | which it is being read, NAME is its file name, and ELF_HEADER is | ||
| 403 | its header. | ||
| 404 | |||
| 405 | If ELF_HEADER->e_type is ET_DYN, add the base address for position | ||
| 406 | independent interpreter code to virtual addresses. | ||
| 407 | |||
| 408 | Value is 1 upon failure, else 0. */ | ||
| 409 | |||
| 410 | static int | ||
| 411 | process_interpreter_1 (const char *name, int fd, | ||
| 412 | program_header *header, | ||
| 413 | elf_header *elf_header) | ||
| 414 | { | ||
| 415 | int rc; | ||
| 416 | #if defined __mips__ && !defined MIPS_NABI | ||
| 417 | ssize_t rc1; | ||
| 418 | #endif /* defined __mips__ && !defined MIPS_NABI */ | ||
| 419 | |||
| 420 | switch (header->p_type) | ||
| 421 | { | ||
| 422 | default: /* PT_NULL, PT_NOTE, PT_DYNAMIC, PT_INTERP, et cetera */ | ||
| 423 | rc = 0; | ||
| 424 | break; | ||
| 425 | |||
| 426 | case 1: /* PT_LOAD */ | ||
| 427 | /* This describes a segment in the file that must be loaded. | ||
| 428 | Write the appropriate load command. */ | ||
| 429 | |||
| 430 | if (elf_header->e_type == 3) /* ET_DYN */ | ||
| 431 | rc = write_load_command (header, true, | ||
| 432 | INTERPRETER_BASE); | ||
| 433 | else | ||
| 434 | rc = write_load_command (header, true, 0); | ||
| 435 | |||
| 436 | break; | ||
| 437 | |||
| 438 | #if defined __mips__ && !defined MIPS_NABI | ||
| 439 | case 0x70000003: /* PT_MIPS_ABIFLAGS */ | ||
| 440 | /* Record this header for later use. */ | ||
| 441 | rc1 = pread (fd, &interpreter_abi, sizeof interpreter_abi, | ||
| 442 | header->p_offset); | ||
| 443 | |||
| 444 | if (rc1 != sizeof interpreter_abi) | ||
| 445 | return 1; | ||
| 446 | |||
| 447 | interpreter_abiflags = &interpreter_abi; | ||
| 448 | rc = 0; | ||
| 449 | #endif /* defined __mips__ && !defined MIPS_NABI */ | ||
| 450 | } | ||
| 451 | |||
| 452 | return rc; | ||
| 453 | } | ||
| 454 | |||
| 455 | /* Read the ELF interpreter specified in the given program header from | ||
| 456 | FD, and append the commands necessary to load it to the load area. | ||
| 457 | Then, return the interpreter entry point in *ENTRY. | ||
| 458 | |||
| 459 | Value is 1 upon failure, else 0. */ | ||
| 460 | |||
| 461 | static int | ||
| 462 | process_interpreter (int fd, program_header *prog_header, | ||
| 463 | USER_WORD *entry) | ||
| 464 | { | ||
| 465 | char buffer[PATH_MAX + 1]; | ||
| 466 | int rc, size, i; | ||
| 467 | elf_header header; | ||
| 468 | program_header program; | ||
| 469 | |||
| 470 | /* Read the interpreter name. */ | ||
| 471 | size = MIN (prog_header->p_filesz, PATH_MAX); | ||
| 472 | rc = pread (fd, buffer, size, prog_header->p_offset); | ||
| 473 | if (rc < size) | ||
| 474 | return 1; | ||
| 475 | |||
| 476 | /* Make sure the name is NULL terminated. */ | ||
| 477 | buffer[size] = '\0'; | ||
| 478 | |||
| 479 | /* Check if the file is executable. This is unfortunately not | ||
| 480 | atomic. */ | ||
| 481 | |||
| 482 | if (access (buffer, X_OK)) | ||
| 483 | return 1; | ||
| 484 | |||
| 485 | /* Read the interpreter's header much like exec_0. | ||
| 486 | |||
| 487 | However, use special command codes in `process_program_header' if | ||
| 488 | it is position independent. That way, the loader knows it should | ||
| 489 | use the open interpreter instead. */ | ||
| 490 | |||
| 491 | fd = open (buffer, O_RDONLY); | ||
| 492 | |||
| 493 | if (fd < 0) | ||
| 494 | return 1; | ||
| 495 | |||
| 496 | rc = read (fd, &header, sizeof header); | ||
| 497 | |||
| 498 | if (rc < sizeof header) | ||
| 499 | goto fail; | ||
| 500 | |||
| 501 | #if defined __mips__ && !defined MIPS_NABI | ||
| 502 | /* Record this interpreter's header for later use determining the | ||
| 503 | floating point ABI. */ | ||
| 504 | exec_interpreter_header = header; | ||
| 505 | interpreter_header = &exec_interpreter_header; | ||
| 506 | #endif /* defined __mips__ && !defined MIPS_NABI */ | ||
| 507 | |||
| 508 | /* Verify that this is indeed an ELF file. */ | ||
| 509 | |||
| 510 | if (header.e_ident[0] != 0x7f | ||
| 511 | || header.e_ident[1] != 'E' | ||
| 512 | || header.e_ident[2] != 'L' | ||
| 513 | || header.e_ident[3] != 'F') | ||
| 514 | goto fail; | ||
| 515 | |||
| 516 | /* Now check that the class is correct. */ | ||
| 517 | #ifdef EXEC_64 | ||
| 518 | if (header.e_ident[4] != 2) | ||
| 519 | goto fail; | ||
| 520 | #else /* !EXEC_64 */ | ||
| 521 | if (header.e_ident[4] != 1) | ||
| 522 | goto fail; | ||
| 523 | #endif /* EXEC_64 */ | ||
| 524 | |||
| 525 | /* And the endianness. */ | ||
| 526 | #ifndef WORDS_BIGENDIAN | ||
| 527 | if (header.e_ident[5] != 1) | ||
| 528 | goto fail; | ||
| 529 | #else /* WORDS_BIGENDIAN */ | ||
| 530 | if (header.e_ident[5] != 2) | ||
| 531 | goto fail; | ||
| 532 | #endif /* EXEC_64 */ | ||
| 533 | |||
| 534 | /* Check that this is an executable. */ | ||
| 535 | if (header.e_type != 2 && header.e_type != 3) | ||
| 536 | goto fail; | ||
| 537 | |||
| 538 | /* Now check that the ELF program header makes sense. */ | ||
| 539 | if (header.e_phnum > 0xffff | ||
| 540 | || (header.e_phentsize | ||
| 541 | != sizeof (program_header))) | ||
| 542 | goto fail; | ||
| 543 | |||
| 544 | if (write_open_command (buffer, true)) | ||
| 545 | goto fail; | ||
| 546 | |||
| 547 | for (i = 0; i < header.e_phnum; ++i) | ||
| 548 | { | ||
| 549 | rc = read (fd, &program, sizeof program); | ||
| 550 | if (rc < sizeof program) | ||
| 551 | goto fail; | ||
| 552 | |||
| 553 | if (process_interpreter_1 (buffer, fd, &program, | ||
| 554 | &header)) | ||
| 555 | goto fail; | ||
| 556 | } | ||
| 557 | |||
| 558 | if (header.e_type == 3) /* ET_DYN */ | ||
| 559 | *entry = header.e_entry + INTERPRETER_BASE; | ||
| 560 | else | ||
| 561 | *entry = header.e_entry; | ||
| 562 | |||
| 563 | close (fd); | ||
| 564 | return 0; | ||
| 565 | |||
| 566 | fail: | ||
| 567 | close (fd); | ||
| 568 | return 1; | ||
| 569 | } | ||
| 570 | |||
| 571 | /* Process the specified program HEADER. FD is the executable file | ||
| 572 | from which it is being read, NAME is its file name, and ELF_HEADER | ||
| 573 | is its header. | ||
| 574 | |||
| 575 | If ELF_HEADER->e_type is ET_DYN, add the base address for position | ||
| 576 | independent code to virtual addresses. | ||
| 577 | |||
| 578 | If OFFSET is non-NULL, and *OFFSET is -1, write the virtual address | ||
| 579 | of HEADER if it describes a PT_LOAD segment. | ||
| 580 | |||
| 581 | If an interpreter is found, set *ENTRY to its entry point. | ||
| 582 | |||
| 583 | Value is 1 upon failure, else 0. */ | ||
| 584 | |||
| 585 | static int | ||
| 586 | process_program_header (const char *name, int fd, | ||
| 587 | program_header *header, | ||
| 588 | elf_header *elf_header, | ||
| 589 | USER_WORD *entry, | ||
| 590 | USER_WORD *offset) | ||
| 591 | { | ||
| 592 | int rc; | ||
| 593 | #if defined __mips__ && !defined MIPS_NABI | ||
| 594 | ssize_t rc1; | ||
| 595 | #endif /* defined __mips__ && !defined MIPS_NABI */ | ||
| 596 | |||
| 597 | switch (header->p_type) | ||
| 598 | { | ||
| 599 | default: /* PT_NULL, PT_NOTE, PT_DYNAMIC, et cetera */ | ||
| 600 | rc = 0; | ||
| 601 | break; | ||
| 602 | |||
| 603 | case 1: /* PT_LOAD */ | ||
| 604 | /* This describes a segment in the file that must be loaded. | ||
| 605 | Write the appropriate load command. */ | ||
| 606 | |||
| 607 | if (elf_header->e_type == 3) /* ET_DYN */ | ||
| 608 | { | ||
| 609 | rc = write_load_command (header, false, | ||
| 610 | EXECUTABLE_BASE); | ||
| 611 | |||
| 612 | if (!rc && offset && *offset == (USER_WORD) -1) | ||
| 613 | *offset = EXECUTABLE_BASE + header->p_vaddr; | ||
| 614 | } | ||
| 615 | else | ||
| 616 | { | ||
| 617 | rc = write_load_command (header, false, 0); | ||
| 618 | |||
| 619 | if (!rc && offset && *offset == (USER_WORD) -1) | ||
| 620 | *offset = header->p_vaddr; | ||
| 621 | } | ||
| 622 | |||
| 623 | break; | ||
| 624 | |||
| 625 | case 3: /* PT_INTERP */ | ||
| 626 | /* This describes another executable that must be loaded. | ||
| 627 | Open the interpreter and process each of its headers | ||
| 628 | as well. */ | ||
| 629 | rc = process_interpreter (fd, header, entry); | ||
| 630 | break; | ||
| 631 | |||
| 632 | case 1685382481: /* PT_GNU_STACK */ | ||
| 633 | /* TODO */ | ||
| 634 | rc = 0; | ||
| 635 | break; | ||
| 636 | |||
| 637 | #if defined __mips__ && !defined MIPS_NABI | ||
| 638 | case 0x70000003: /* PT_MIPS_ABIFLAGS */ | ||
| 639 | /* Record this header for later use. */ | ||
| 640 | rc1 = pread (fd, &exec_abi, sizeof exec_abi, | ||
| 641 | header->p_offset); | ||
| 642 | |||
| 643 | if (rc1 != sizeof exec_abi) | ||
| 644 | return 1; | ||
| 645 | |||
| 646 | exec_abiflags = &exec_abi; | ||
| 647 | rc = 0; | ||
| 648 | #endif /* defined __mips__ && !defined MIPS_NABI */ | ||
| 649 | } | ||
| 650 | |||
| 651 | return rc; | ||
| 652 | } | ||
| 653 | |||
| 654 | /* Prepend one or two extra arguments ARG1 and ARG2 to a pending | ||
| 655 | execve system call. TRACEE is the tracee performing the system | ||
| 656 | call, and REGS are its current user registers. Value is 1 upon | ||
| 657 | failure, else 0. */ | ||
| 658 | |||
| 659 | static int | ||
| 660 | insert_args (struct exec_tracee *tracee, USER_REGS_STRUCT *regs, | ||
| 661 | const char *arg1, const char *arg2) | ||
| 662 | { | ||
| 663 | USER_WORD argv, argc, word, new; | ||
| 664 | USER_WORD new1, new2; | ||
| 665 | size_t text_size, effective_size; | ||
| 666 | USER_REGS_STRUCT original; | ||
| 667 | |||
| 668 | /* First, get a pointer to the current argument vector. */ | ||
| 669 | argv = regs->SYSCALL_ARG1_REG; | ||
| 670 | |||
| 671 | /* Now figure out how many arguments there are. */ | ||
| 672 | argc = 0; | ||
| 673 | while (true) | ||
| 674 | { | ||
| 675 | /* Clear errno. PTRACE_PEEKDATA returns the word read the same | ||
| 676 | way failure indications are returned, so the only way to | ||
| 677 | catch IO errors is by clearing errno before the call to | ||
| 678 | ptrace and checking it afterwards. */ | ||
| 679 | |||
| 680 | errno = 0; | ||
| 681 | word = ptrace (PTRACE_PEEKDATA, tracee->pid, | ||
| 682 | (void *) argv, NULL); | ||
| 683 | argv += sizeof (USER_WORD); | ||
| 684 | |||
| 685 | if (errno) | ||
| 686 | return 1; | ||
| 687 | |||
| 688 | if (!word) | ||
| 689 | break; | ||
| 690 | |||
| 691 | ++argc; | ||
| 692 | }; | ||
| 693 | |||
| 694 | /* Allocate enough to hold that many arguments, alongside the argc | ||
| 695 | text. */ | ||
| 696 | |||
| 697 | text_size = (strlen (arg1) + 1 | ||
| 698 | + (arg2 ? strlen (arg2) + 1 : 0)); | ||
| 699 | |||
| 700 | /* Round it up to the user word size. */ | ||
| 701 | text_size += sizeof (USER_WORD) - 1; | ||
| 702 | text_size &= ~(sizeof (USER_WORD) - 1); | ||
| 703 | |||
| 704 | /* Now allocate the new argv. */ | ||
| 705 | |||
| 706 | effective_size = sizeof word * (argc + 2) + text_size; | ||
| 707 | |||
| 708 | if (arg2) | ||
| 709 | effective_size += sizeof word; | ||
| 710 | |||
| 711 | /* Copy regs to original so that user_alloca knows it should append | ||
| 712 | the ABI red zone. */ | ||
| 713 | |||
| 714 | memcpy (&original, regs, sizeof *regs); | ||
| 715 | new = user_alloca (tracee, &original, regs, | ||
| 716 | effective_size); | ||
| 717 | |||
| 718 | if (!new) | ||
| 719 | goto fail; | ||
| 720 | |||
| 721 | /* Figure out where argv starts. */ | ||
| 722 | |||
| 723 | new2 = new + text_size; | ||
| 724 | |||
| 725 | /* Now write the two strings. */ | ||
| 726 | |||
| 727 | new1 = new + strlen (arg1) + 1; | ||
| 728 | if (user_copy (tracee, (const unsigned char *) arg1, | ||
| 729 | new, new1 - new)) | ||
| 730 | goto fail; | ||
| 731 | |||
| 732 | if (arg2 && user_copy (tracee, (const unsigned char *) arg2, | ||
| 733 | new1, new2 - new1)) | ||
| 734 | goto fail; | ||
| 735 | |||
| 736 | /* Start copying argv back to new2. First, write the one or two new | ||
| 737 | arguments. */ | ||
| 738 | |||
| 739 | if (ptrace (PTRACE_POKETEXT, tracee->pid, | ||
| 740 | (void *) new2, (void *) new)) | ||
| 741 | goto fail; | ||
| 742 | |||
| 743 | new2 += sizeof new2; | ||
| 744 | |||
| 745 | if (arg2 && ptrace (PTRACE_POKETEXT, tracee->pid, | ||
| 746 | (void *) new2, (void *) new1)) | ||
| 747 | goto fail; | ||
| 748 | else if (arg2) | ||
| 749 | new2 += sizeof new2; | ||
| 750 | |||
| 751 | /* Copy the remaining arguments back. */ | ||
| 752 | |||
| 753 | argv = regs->SYSCALL_ARG1_REG; | ||
| 754 | |||
| 755 | /* Make sure the trailing NULL is included. */ | ||
| 756 | argc += 1; | ||
| 757 | |||
| 758 | while (argc) | ||
| 759 | { | ||
| 760 | /* Read one argument. */ | ||
| 761 | word = ptrace (PTRACE_PEEKDATA, tracee->pid, | ||
| 762 | (void *) argv, NULL); | ||
| 763 | argv += sizeof argv; | ||
| 764 | argc--; | ||
| 765 | |||
| 766 | /* Write one argument, then increment new2. */ | ||
| 767 | |||
| 768 | if (ptrace (PTRACE_POKETEXT, tracee->pid, | ||
| 769 | (void *) new2, (void *) word)) | ||
| 770 | goto fail; | ||
| 771 | |||
| 772 | new2 += sizeof new2; | ||
| 773 | } | ||
| 774 | |||
| 775 | /* Assert that new2 is not out of bounds. */ | ||
| 776 | assert (new2 == new + effective_size); | ||
| 777 | |||
| 778 | /* And that it is properly aligned. */ | ||
| 779 | assert (!(new2 & (sizeof new2 - 2))); | ||
| 780 | |||
| 781 | /* Now modify the system call argument to point to new + | ||
| 782 | text_size. */ | ||
| 783 | |||
| 784 | regs->SYSCALL_ARG1_REG = new + text_size; | ||
| 785 | |||
| 786 | #ifdef __aarch64__ | ||
| 787 | if (aarch64_set_regs (tracee->pid, regs, false)) | ||
| 788 | goto fail; | ||
| 789 | #else /* !__aarch64__ */ | ||
| 790 | if (ptrace (PTRACE_SETREGS, tracee->pid, NULL, regs)) | ||
| 791 | goto fail; | ||
| 792 | #endif /* __aarch64__ */ | ||
| 793 | |||
| 794 | /* Success. */ | ||
| 795 | |||
| 796 | return 0; | ||
| 797 | |||
| 798 | fail: | ||
| 799 | /* Restore the original stack pointer. */ | ||
| 800 | #ifdef __aarch64__ | ||
| 801 | aarch64_set_regs (tracee->pid, &original, false); | ||
| 802 | #else /* !__aarch64__ */ | ||
| 803 | ptrace (PTRACE_SETREGS, tracee->pid, NULL, &original); | ||
| 804 | #endif /* __aarch64__ */ | ||
| 805 | errno = ENOMEM; | ||
| 806 | return 1; | ||
| 807 | } | ||
| 808 | |||
| 809 | |||
| 810 | |||
| 811 | /* Return a sequence of actions required to load the executable under | ||
| 812 | the file NAME for the given TRACEE. First, see if the file starts | ||
| 813 | with #!; in that case, find the program to open and use that | ||
| 814 | instead. | ||
| 815 | |||
| 816 | Next, read the executable header, and add the necessary memory | ||
| 817 | mappings for each file. Finally, return the action data and its | ||
| 818 | size in *SIZE. | ||
| 819 | |||
| 820 | Finally, use REGS to add the required interpreter arguments to the | ||
| 821 | caller's argv. | ||
| 822 | |||
| 823 | Value is NULL upon failure, with errno set accordingly. */ | ||
| 824 | |||
| 825 | char * | ||
| 826 | exec_0 (const char *name, struct exec_tracee *tracee, | ||
| 827 | size_t *size, USER_REGS_STRUCT *regs) | ||
| 828 | { | ||
| 829 | int fd, rc, i; | ||
| 830 | elf_header header; | ||
| 831 | const char *interpreter_name, *extra; | ||
| 832 | program_header program; | ||
| 833 | USER_WORD entry, program_entry, offset; | ||
| 834 | USER_WORD header_offset; | ||
| 835 | struct exec_jump_command jump; | ||
| 836 | #if defined __mips__ && !defined MIPS_NABI | ||
| 837 | int fpu_mode; | ||
| 838 | #endif /* defined __mips__ && !defined MIPS_NABI */ | ||
| 839 | |||
| 840 | fd = open (name, O_RDONLY); | ||
| 841 | if (fd < 0) | ||
| 842 | return NULL; | ||
| 843 | |||
| 844 | /* Now read the header. */ | ||
| 845 | |||
| 846 | extra = NULL; | ||
| 847 | interpreter_name = check_interpreter (name, fd, &extra); | ||
| 848 | if (!interpreter_name) | ||
| 849 | goto fail; | ||
| 850 | |||
| 851 | /* Open the interpreter instead, if necessary. */ | ||
| 852 | if (interpreter_name != name) | ||
| 853 | { | ||
| 854 | close (fd); | ||
| 855 | fd = open (interpreter_name, O_RDONLY); | ||
| 856 | if (fd < 0) | ||
| 857 | return NULL; | ||
| 858 | |||
| 859 | /* Now, rewrite the argument list to include `interpreter_name' | ||
| 860 | and perhaps `extra'. */ | ||
| 861 | |||
| 862 | if (insert_args (tracee, regs, interpreter_name, | ||
| 863 | extra)) | ||
| 864 | goto fail1; | ||
| 865 | } | ||
| 866 | |||
| 867 | rc = read (fd, &header, sizeof header); | ||
| 868 | |||
| 869 | if (rc < sizeof header) | ||
| 870 | goto fail1; | ||
| 871 | |||
| 872 | /* Verify that this is indeed an ELF file. */ | ||
| 873 | |||
| 874 | if (header.e_ident[0] != 0x7f | ||
| 875 | || header.e_ident[1] != 'E' | ||
| 876 | || header.e_ident[2] != 'L' | ||
| 877 | || header.e_ident[3] != 'F') | ||
| 878 | goto fail1; | ||
| 879 | |||
| 880 | /* Now check that the class is correct. */ | ||
| 881 | #ifdef EXEC_64 | ||
| 882 | if (header.e_ident[4] != 2) | ||
| 883 | goto fail1; | ||
| 884 | #else /* !EXEC_64 */ | ||
| 885 | if (header.e_ident[4] != 1) | ||
| 886 | goto fail1; | ||
| 887 | #endif /* EXEC_64 */ | ||
| 888 | |||
| 889 | /* And the endianness. */ | ||
| 890 | #ifndef WORDS_BIGENDIAN | ||
| 891 | if (header.e_ident[5] != 1) | ||
| 892 | goto fail1; | ||
| 893 | #else /* WORDS_BIGENDIAN */ | ||
| 894 | if (header.e_ident[5] != 2) | ||
| 895 | goto fail1; | ||
| 896 | #endif /* EXEC_64 */ | ||
| 897 | |||
| 898 | /* Check that this is an executable. */ | ||
| 899 | if (header.e_type != 2 && header.e_type != 3) | ||
| 900 | goto fail1; | ||
| 901 | |||
| 902 | /* Now check that the ELF program header makes sense. */ | ||
| 903 | if (header.e_phnum > 0xffff | ||
| 904 | || (header.e_phentsize | ||
| 905 | != sizeof (program_header))) | ||
| 906 | goto fail1; | ||
| 907 | |||
| 908 | /* Seek to the first program header and read each one. */ | ||
| 909 | rc = lseek (fd, header.e_phoff, SEEK_SET); | ||
| 910 | if (rc < 0) | ||
| 911 | goto fail1; | ||
| 912 | loader_area_used = 0; | ||
| 913 | |||
| 914 | /* Write the command used to open the executable. */ | ||
| 915 | if (write_open_command (interpreter_name, false)) | ||
| 916 | goto fail1; | ||
| 917 | |||
| 918 | /* Apply base addresses for PIC code. */ | ||
| 919 | |||
| 920 | if (header.e_type == 3) /* ET_DYN */ | ||
| 921 | offset = EXECUTABLE_BASE; | ||
| 922 | else | ||
| 923 | offset = 0; | ||
| 924 | |||
| 925 | /* entry and program_entry are initially the same, but entry may be | ||
| 926 | set to that of the interpreter if one is present. */ | ||
| 927 | |||
| 928 | entry = header.e_entry + offset; | ||
| 929 | program_entry = header.e_entry; | ||
| 930 | |||
| 931 | #if defined __mips__ && !defined MIPS_NABI | ||
| 932 | /* Clear MIPS ABI flags. */ | ||
| 933 | exec_abiflags = NULL; | ||
| 934 | interpreter_abiflags = NULL; | ||
| 935 | interpreter_header = NULL; | ||
| 936 | #endif /* defined __mips__ && !defined MIPS_NABI */ | ||
| 937 | |||
| 938 | /* Set header_offset to -1; `process_program_header' then updates it | ||
| 939 | to that of the first mapping. */ | ||
| 940 | header_offset = -1; | ||
| 941 | |||
| 942 | for (i = 0; i < header.e_phnum; ++i) | ||
| 943 | { | ||
| 944 | rc = read (fd, &program, sizeof program); | ||
| 945 | if (rc < sizeof program) | ||
| 946 | goto fail1; | ||
| 947 | |||
| 948 | if (process_program_header (interpreter_name, fd, | ||
| 949 | &program, &header, | ||
| 950 | &entry, &header_offset)) | ||
| 951 | goto fail1; | ||
| 952 | } | ||
| 953 | |||
| 954 | /* Write the entry point and program entry. */ | ||
| 955 | |||
| 956 | jump.command = 3; | ||
| 957 | jump.entry = entry; | ||
| 958 | |||
| 959 | /* Now calculate values for the aux vector. */ | ||
| 960 | |||
| 961 | jump.at_entry = program_entry + offset; | ||
| 962 | jump.at_phent = header.e_phentsize; | ||
| 963 | jump.at_phnum = header.e_phnum; | ||
| 964 | jump.at_base = (entry == header.e_entry + offset | ||
| 965 | ? EXECUTABLE_BASE | ||
| 966 | : INTERPRETER_BASE); | ||
| 967 | |||
| 968 | #if defined __mips__ && !defined MIPS_NABI | ||
| 969 | /* Finally, calculate the FPU mode wanted by the executable. */ | ||
| 970 | |||
| 971 | if (determine_fpu_mode (&header, interpreter_header, | ||
| 972 | &fpu_mode, exec_abiflags, | ||
| 973 | interpreter_abiflags)) | ||
| 974 | /* N.B. that `determine_fpu_mode' sets errno. */ | ||
| 975 | goto fail; | ||
| 976 | |||
| 977 | /* If the processor is too new to support FR0 operation, place the | ||
| 978 | executable in floating point emulation mode. */ | ||
| 979 | |||
| 980 | if (fpu_mode == FP_FR0 && !cpu_supports_fr0_p ()) | ||
| 981 | fpu_mode = FP_FRE; | ||
| 982 | |||
| 983 | jump.fpu_mode = fpu_mode; | ||
| 984 | #endif /* defined __mips__ && !defined MIPS_NABI */ | ||
| 985 | |||
| 986 | /* The offset used for at_phdr should be that of the first | ||
| 987 | mapping. */ | ||
| 988 | |||
| 989 | if (header_offset == (USER_WORD) -1) | ||
| 990 | header_offset = 0; | ||
| 991 | |||
| 992 | jump.at_phdr = header.e_phoff + header_offset; | ||
| 993 | |||
| 994 | if (sizeof loader_area - loader_area_used < sizeof jump) | ||
| 995 | goto fail1; | ||
| 996 | |||
| 997 | memcpy (loader_area + loader_area_used, &jump, | ||
| 998 | sizeof jump); | ||
| 999 | loader_area_used += sizeof jump; | ||
| 1000 | |||
| 1001 | /* Close the file descriptor and return the number of bytes | ||
| 1002 | used. */ | ||
| 1003 | |||
| 1004 | close (fd); | ||
| 1005 | *size = loader_area_used; | ||
| 1006 | |||
| 1007 | /* Make sure the loader area is properly aligned. */ | ||
| 1008 | assert (!(loader_area_used & (sizeof (USER_WORD) - 1))); | ||
| 1009 | return loader_area; | ||
| 1010 | |||
| 1011 | fail1: | ||
| 1012 | errno = ENOEXEC; | ||
| 1013 | fail: | ||
| 1014 | close (fd); | ||
| 1015 | return NULL; | ||
| 1016 | } | ||