This source file includes following definitions.
- rpl_stpcpy
- rpl_stpncpy
- check_interpreter
- write_open_command
- write_load_command
- process_interpreter_1
- process_interpreter
- process_program_header
- insert_args
- format_pid
- exec_0
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 #include <config.h>
21
22 #include <errno.h>
23 #include <unistd.h>
24 #include <fcntl.h>
25 #include <assert.h>
26 #include <string.h>
27 #include <ctype.h>
28 #include <stdlib.h>
29
30 #include <sys/ptrace.h>
31 #include <sys/param.h>
32 #include <sys/mman.h>
33
34 #include "exec.h"
35
36 #if defined __mips__ && !defined MIPS_NABI
37 #include "mipsfpu.h"
38 #endif
39
40
41
42
43
44
45 #if !defined HAVE_STPCPY || !defined HAVE_DECL_STPCPY
46
47
48
49
50 static char *
51 rpl_stpcpy (char *dest, const char *src)
52 {
53 register char *d;
54 register const char *s;
55
56 d = dest;
57 s = src;
58
59 do
60 *d++ = *s;
61 while (*s++ != '\0');
62
63 return d - 1;
64 }
65
66 #define stpcpy rpl_stpcpy
67 #endif
68
69 #if !defined HAVE_STPNCPY || !defined HAVE_DECL_STPNCPY
70
71
72
73
74 static char *
75 rpl_stpncpy (char *dest, const char *src, size_t n)
76 {
77 char c, *s;
78 size_t n4;
79
80 s = dest;
81
82 if (n >= 4)
83 {
84 n4 = n >> 2;
85
86 for (;;)
87 {
88 c = *src++;
89 *dest++ = c;
90 if (c == '\0')
91 break;
92 c = *src++;
93 *dest++ = c;
94 if (c == '\0')
95 break;
96 c = *src++;
97 *dest++ = c;
98 if (c == '\0')
99 break;
100 c = *src++;
101 *dest++ = c;
102 if (c == '\0')
103 break;
104 if (--n4 == 0)
105 goto last_chars;
106 }
107 n -= dest - s;
108 goto zero_fill;
109 }
110
111 last_chars:
112 n &= 3;
113 if (n == 0)
114 return dest;
115
116 for (;;)
117 {
118 c = *src++;
119 --n;
120 *dest++ = c;
121 if (c == '\0')
122 break;
123 if (n == 0)
124 return dest;
125 }
126
127 zero_fill:
128 while (n-- > 0)
129 dest[n] = '\0';
130
131 return dest - 1;
132 }
133
134 #define stpncpy rpl_stpncpy
135 #endif
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164 static const char *
165 check_interpreter (const char *name, int fd, const char **extra)
166 {
167 static char buffer[PATH_MAX], *start;
168 char first[2], *end, *ws;
169 ssize_t rc;
170
171
172 rc = read (fd, &first, 2);
173
174 if (rc != 2)
175 goto fail;
176
177 if (first[0] != '#' || first[1] != '!')
178 goto nomatch;
179
180 rc = read (fd, buffer, PATH_MAX);
181
182 if (rc < 0)
183 goto fail;
184
185
186 start = buffer;
187 while (*start && ((unsigned char) *start) < 128 && isspace (*start))
188 ++start;
189
190
191 end = memchr (start, '\n', rc);
192
193 if (!end)
194 goto fail;
195
196
197
198 *end = '\0';
199
200
201 ws = strchr (start, ' ');
202
203
204
205 if (!ws)
206 {
207 if (lseek (fd, 0, SEEK_SET))
208 goto fail;
209
210 return start;
211 }
212
213
214
215 *ws = '\0';
216
217 if (lseek (fd, 0, SEEK_SET))
218 goto fail;
219
220 *extra = ws + 1;
221 return start;
222
223 nomatch:
224
225 if (lseek (fd, 0, SEEK_SET))
226 goto fail;
227
228 return name;
229
230 fail:
231 errno = ENOEXEC;
232 return NULL;
233 }
234
235
236 static char loader_area[65536];
237
238
239 static int loader_area_used;
240
241
242
243
244
245
246 struct exec_open_command
247 {
248
249 USER_WORD command;
250
251
252
253 };
254
255 struct exec_map_command
256 {
257
258 USER_WORD command;
259
260
261 USER_WORD vm_address;
262
263
264 USER_WORD file_offset;
265
266
267 USER_WORD protection;
268
269
270 USER_WORD length;
271
272
273 USER_WORD flags;
274
275
276 USER_WORD clear;
277 };
278
279 struct exec_jump_command
280 {
281
282 USER_WORD command;
283
284
285 USER_WORD entry;
286
287
288 USER_WORD at_entry;
289
290
291 USER_WORD at_phent;
292
293
294 USER_WORD at_phnum;
295
296
297 USER_WORD at_phdr;
298
299
300 USER_WORD at_base;
301
302 #if defined __mips__ && !defined MIPS_NABI
303
304 USER_WORD fpu_mode;
305 #endif
306 };
307
308
309
310
311
312
313
314 static int
315 write_open_command (const char *name, bool alternate)
316 {
317 struct exec_open_command command;
318 size_t size;
319
320
321
322
323 command.command = alternate ? 16 : 0;
324 if (sizeof loader_area - loader_area_used < sizeof command)
325 return 1;
326 memcpy (loader_area + loader_area_used, &command, sizeof command);
327 loader_area_used += sizeof command;
328
329
330 size = strlen (name) + 1;
331
332
333 size = ((size + (sizeof (USER_WORD) - 1))
334 & ~(sizeof (USER_WORD) - 1));
335
336 if (sizeof loader_area - loader_area_used < size)
337 return 1;
338
339
340
341 strncpy (loader_area + loader_area_used, name, size);
342
343
344 loader_area_used += size;
345 return 0;
346 }
347
348
349
350
351
352
353
354
355 static int
356 write_load_command (program_header *header, bool use_alternate,
357 USER_WORD offset)
358 {
359 struct exec_map_command command;
360 struct exec_map_command command1;
361 USER_WORD start, end;
362 bool need_command1;
363 static long pagesize;
364
365
366
367
368
369
370
371 #ifndef PAGE_MASK
372
373
374 #ifdef HAVE_GETPAGESIZE
375 if (!pagesize)
376 pagesize = getpagesize ();
377 #else
378 if (!pagesize)
379 pagesize = sysconf (_SC_PAGESIZE);
380
381 #define PAGE_MASK (~(pagesize - 1))
382 #define PAGE_SIZE (pagesize)
383 #endif
384 #endif
385
386 start = header->p_vaddr & PAGE_MASK;
387 end = ((header->p_vaddr + header->p_filesz
388 + PAGE_SIZE)
389 & PAGE_MASK);
390
391 command.command = use_alternate ? 17 : 1;
392 command.vm_address = start;
393 command.file_offset = header->p_offset & PAGE_MASK;
394 command.protection = 0;
395 command.length = end - start;
396 command.clear = 0;
397 command.flags = MAP_PRIVATE | MAP_FIXED;
398
399
400
401 if (header->p_flags & 4)
402 command.protection |= PROT_READ;
403
404 if (header->p_flags & 2)
405 command.protection |= PROT_WRITE;
406
407 if (header->p_flags & 1)
408 command.protection |= PROT_EXEC;
409
410
411
412 need_command1 = false;
413
414 if (header->p_memsz > header->p_filesz)
415 {
416
417
418 command.clear = end - header->p_vaddr - header->p_filesz;
419 start = end;
420 end = header->p_vaddr + header->p_memsz + PAGE_SIZE;
421 end &= PAGE_MASK;
422
423 if (end > start)
424 {
425 command1.command = 4;
426 command1.vm_address = start;
427 command1.file_offset = 0;
428 command1.length = end - start;
429 command1.clear = 0;
430 command1.protection = command.protection;
431 command1.flags = MAP_PRIVATE | MAP_ANONYMOUS | MAP_FIXED;
432 need_command1 = true;
433 }
434 }
435
436
437
438 if (offset)
439 {
440 if (need_command1)
441 command1.vm_address += offset;
442
443 command.vm_address += offset;
444 }
445
446
447
448 if (sizeof loader_area - loader_area_used < sizeof command)
449 return 1;
450
451 memcpy (loader_area + loader_area_used, &command,
452 sizeof command);
453 loader_area_used += sizeof command;
454
455 if (!need_command1)
456 return 0;
457
458 if (sizeof loader_area - loader_area_used < sizeof command1)
459 return 1;
460
461 memcpy (loader_area + loader_area_used, &command1,
462 sizeof command1);
463 loader_area_used += sizeof command1;
464
465 return 0;
466 }
467
468 #if defined __mips__ && !defined MIPS_NABI
469
470
471 static struct mips_elf_abi_flags exec_abi, interpreter_abi;
472
473
474 static elf_header exec_interpreter_header;
475
476
477 static elf_header *interpreter_header;
478
479
480
481 static struct mips_elf_abi_flags *exec_abiflags;
482
483
484
485 static struct mips_elf_abi_flags *interpreter_abiflags;
486
487 #endif
488
489
490
491
492
493
494
495
496
497
498
499 static int
500 process_interpreter_1 (const char *name, int fd,
501 program_header *header,
502 elf_header *elf_header)
503 {
504 int rc;
505 #if defined __mips__ && !defined MIPS_NABI
506 ssize_t rc1;
507 #endif
508
509 switch (header->p_type)
510 {
511 default:
512 rc = 0;
513 break;
514
515 case 1:
516
517
518
519 if (elf_header->e_type == 3)
520 rc = write_load_command (header, true,
521 INTERPRETER_BASE);
522 else
523 rc = write_load_command (header, true, 0);
524
525 break;
526
527 #if defined __mips__ && !defined MIPS_NABI
528 case 0x70000003:
529
530 rc1 = pread (fd, &interpreter_abi, sizeof interpreter_abi,
531 header->p_offset);
532
533 if (rc1 != sizeof interpreter_abi)
534 return 1;
535
536 interpreter_abiflags = &interpreter_abi;
537 rc = 0;
538 #endif
539 }
540
541 return rc;
542 }
543
544
545
546
547
548
549
550 static int
551 process_interpreter (int fd, program_header *prog_header,
552 USER_WORD *entry)
553 {
554 char buffer[PATH_MAX + 1];
555 int rc, size, i;
556 elf_header header;
557 program_header program;
558
559
560 size = MIN (prog_header->p_filesz, PATH_MAX);
561 rc = pread (fd, buffer, size, prog_header->p_offset);
562 if (rc < size)
563 return 1;
564
565
566 buffer[size] = '\0';
567
568
569
570
571 if (access (buffer, X_OK))
572 return 1;
573
574
575
576
577
578
579
580 fd = open (buffer, O_RDONLY);
581
582 if (fd < 0)
583 return 1;
584
585 rc = read (fd, &header, sizeof header);
586
587 if (rc < sizeof header)
588 goto fail;
589
590 #if defined __mips__ && !defined MIPS_NABI
591
592
593 exec_interpreter_header = header;
594 interpreter_header = &exec_interpreter_header;
595 #endif
596
597
598
599 if (header.e_ident[0] != 0x7f
600 || header.e_ident[1] != 'E'
601 || header.e_ident[2] != 'L'
602 || header.e_ident[3] != 'F')
603 goto fail;
604
605
606 #ifdef EXEC_64
607 if (header.e_ident[4] != 2)
608 goto fail;
609 #else
610 if (header.e_ident[4] != 1)
611 goto fail;
612 #endif
613
614
615 #ifndef WORDS_BIGENDIAN
616 if (header.e_ident[5] != 1)
617 goto fail;
618 #else
619 if (header.e_ident[5] != 2)
620 goto fail;
621 #endif
622
623
624 if (header.e_type != 2 && header.e_type != 3)
625 goto fail;
626
627
628 if (header.e_phnum > 0xffff
629 || (header.e_phentsize
630 != sizeof (program_header)))
631 goto fail;
632
633 if (write_open_command (buffer, true))
634 goto fail;
635
636 for (i = 0; i < header.e_phnum; ++i)
637 {
638 rc = read (fd, &program, sizeof program);
639 if (rc < sizeof program)
640 goto fail;
641
642 if (process_interpreter_1 (buffer, fd, &program,
643 &header))
644 goto fail;
645 }
646
647 if (header.e_type == 3)
648 *entry = header.e_entry + INTERPRETER_BASE;
649 else
650 *entry = header.e_entry;
651
652 close (fd);
653 return 0;
654
655 fail:
656 close (fd);
657 return 1;
658 }
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674 static int
675 process_program_header (const char *name, int fd,
676 program_header *header,
677 elf_header *elf_header,
678 USER_WORD *entry,
679 USER_WORD *offset)
680 {
681 int rc;
682 #if defined __mips__ && !defined MIPS_NABI
683 ssize_t rc1;
684 #endif
685
686 switch (header->p_type)
687 {
688 default:
689 rc = 0;
690 break;
691
692 case 1:
693
694
695
696 if (elf_header->e_type == 3)
697 {
698 rc = write_load_command (header, false,
699 EXECUTABLE_BASE);
700
701 if (!rc && offset && *offset == (USER_WORD) -1)
702 *offset = EXECUTABLE_BASE + header->p_vaddr;
703 }
704 else
705 {
706 rc = write_load_command (header, false, 0);
707
708 if (!rc && offset && *offset == (USER_WORD) -1)
709 *offset = header->p_vaddr;
710 }
711
712 break;
713
714 case 3:
715
716
717 rc = process_interpreter (fd, header, entry);
718 break;
719
720 case 1685382481:
721
722 rc = 0;
723 break;
724
725 #if defined __mips__ && !defined MIPS_NABI
726 case 0x70000003:
727
728 rc1 = pread (fd, &exec_abi, sizeof exec_abi,
729 header->p_offset);
730
731 if (rc1 != sizeof exec_abi)
732 return 1;
733
734 exec_abiflags = &exec_abi;
735 rc = 0;
736 #endif
737 }
738
739 return rc;
740 }
741
742
743
744
745
746
747
748
749 static int
750 insert_args (struct exec_tracee *tracee, USER_REGS_STRUCT *regs,
751 const char *arg1, const char *arg2, const char *arg3)
752 {
753 USER_WORD argv, argc, word, new;
754 USER_WORD new1, new2, new3, i;
755 size_t text_size, effective_size;
756 USER_REGS_STRUCT original;
757
758
759 argv = regs->SYSCALL_ARG1_REG;
760
761
762 argc = 0;
763 while (true)
764 {
765
766
767
768
769
770 errno = 0;
771 word = ptrace (PTRACE_PEEKDATA, tracee->pid,
772 (void *) argv, NULL);
773 argv += sizeof (USER_WORD);
774
775 if (errno)
776 return 1;
777
778 if (!word)
779 break;
780
781 ++argc;
782 };
783
784
785
786
787 text_size = (strlen (arg1) + 1
788 + (arg2 ? strlen (arg2) + 1 : 0)
789 + strlen (arg3) + 1);
790
791
792 text_size += sizeof (USER_WORD) - 1;
793 text_size &= ~(sizeof (USER_WORD) - 1);
794
795
796
797
798 effective_size = sizeof word * (MAX (1, argc) + 2) + text_size;
799
800 if (arg2)
801 effective_size += sizeof word;
802
803
804
805
806 memcpy (&original, regs, sizeof *regs);
807 new = user_alloca (tracee, &original, regs,
808 effective_size);
809
810 if (!new)
811 goto fail;
812
813
814
815 new3 = new + text_size;
816
817
818
819 new1 = new + strlen (arg1) + 1;
820 new2 = new1 + (arg2 ? strlen (arg2) + 1 : 0);
821
822 if (user_copy (tracee, (const unsigned char *) arg1,
823 new, new1 - new))
824 goto fail;
825
826 if (arg2 && user_copy (tracee, (const unsigned char *) arg2,
827 new1, new2 - new1))
828 goto fail;
829
830
831
832 if (user_copy (tracee, (const unsigned char *) arg3,
833 new2, new3 - new2))
834 goto fail;
835
836
837
838
839 if (ptrace (PTRACE_POKETEXT, tracee->pid,
840 (void *) new3, (void *) new))
841 goto fail;
842
843 new3 += sizeof new3;
844
845 if (arg2 && ptrace (PTRACE_POKETEXT, tracee->pid,
846 (void *) new3, (void *) new1))
847 goto fail;
848 else if (arg2)
849 new3 += sizeof new3;
850
851
852
853 if (ptrace (PTRACE_POKETEXT, tracee->pid, (void *) new3,
854 (void *) new2))
855 goto fail;
856
857 new3 += sizeof new3;
858
859
860
861 argv = regs->SYSCALL_ARG1_REG;
862
863 if (argc)
864 {
865
866 argc += 1;
867
868
869
870 for (i = 1; i < argc; ++i)
871 {
872
873 word = ptrace (PTRACE_PEEKDATA, tracee->pid,
874 (void *) (argv + i * sizeof argv), NULL);
875
876
877
878 if (ptrace (PTRACE_POKETEXT, tracee->pid,
879 (void *) new3, (void *) word))
880 goto fail;
881
882 new3 += sizeof new3;
883 }
884 }
885 else
886 {
887
888
889 if (ptrace (PTRACE_POKETEXT, tracee->pid,
890 (void *) new3, (void *) 0))
891 goto fail;
892
893 new3 += sizeof new3;
894 }
895
896
897 assert (new3 == new + effective_size);
898
899
900 assert (!(new3 & (sizeof new3 - 2)));
901
902
903
904
905 regs->SYSCALL_ARG1_REG = new + text_size;
906
907 #ifdef __aarch64__
908 if (aarch64_set_regs (tracee->pid, regs, false))
909 goto fail;
910 #else
911 if (ptrace (PTRACE_SETREGS, tracee->pid, NULL, regs))
912 goto fail;
913 #endif
914
915
916
917 return 0;
918
919 fail:
920
921 #ifdef __aarch64__
922 aarch64_set_regs (tracee->pid, &original, false);
923 #else
924 ptrace (PTRACE_SETREGS, tracee->pid, NULL, &original);
925 #endif
926 errno = ENOMEM;
927 return 1;
928 }
929
930
931
932
933
934
935
936 static char *
937 format_pid (char *in, unsigned int pid)
938 {
939 unsigned int digits[32], *fill;
940
941 fill = digits;
942
943 for (; pid != 0; pid = pid / 10)
944 *fill++ = pid % 10;
945
946
947
948 if (fill == digits)
949 *fill++ = 0;
950
951 while (fill != digits)
952 {
953 --fill;
954 *in++ = '0' + *fill;
955 }
956
957 *in = '\0';
958 return in;
959 }
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979 char *
980 exec_0 (char *name, struct exec_tracee *tracee,
981 size_t *size, USER_REGS_STRUCT *regs)
982 {
983 int fd, rc, i;
984 elf_header header;
985 const char *interpreter_name, *extra;
986 program_header program;
987 USER_WORD entry, program_entry, offset;
988 USER_WORD header_offset;
989 struct exec_jump_command jump;
990 #if defined __mips__ && !defined MIPS_NABI
991 int fpu_mode;
992 #endif
993 char buffer[80], buffer1[PATH_MAX + 80], *rewrite;
994 ssize_t link_size;
995 size_t remaining;
996
997
998
999
1000 if (!strcmp (name, "/proc/self/exe") && tracee->exec_file)
1001 {
1002 strncpy (name, tracee->exec_file, PATH_MAX - 1);
1003 name[PATH_MAX] = '\0';
1004 }
1005 else
1006 {
1007
1008
1009
1010 if (name[0] && name[0] != '/')
1011 {
1012
1013 memset (buffer, 0, sizeof buffer);
1014 memset (buffer1, 0, sizeof buffer);
1015
1016
1017 rewrite = stpcpy (buffer, "/proc/");
1018 rewrite = format_pid (rewrite, tracee->pid);
1019 strcpy (rewrite, "/cwd");
1020
1021
1022
1023 link_size = readlink (buffer, buffer1,
1024 PATH_MAX + 1);
1025
1026 if (link_size < 0)
1027 return NULL;
1028
1029
1030
1031 if (link_size > PATH_MAX)
1032 {
1033
1034 errno = ENAMETOOLONG;
1035 return NULL;
1036 }
1037
1038
1039
1040 if (!link_size || buffer1[link_size - 1] != '/')
1041 buffer1[link_size] = '/', link_size++;
1042
1043 rewrite = buffer1 + link_size;
1044 remaining = buffer1 + sizeof buffer1 - rewrite - 1;
1045 rewrite = stpncpy (rewrite, name, remaining);
1046
1047
1048 #ifndef REENTRANT
1049 strcpy (name, buffer1);
1050 #endif
1051 }
1052 }
1053
1054
1055
1056 if (access (name, X_OK))
1057 return NULL;
1058
1059 fd = open (name, O_RDONLY);
1060 if (fd < 0)
1061 return NULL;
1062
1063
1064
1065 extra = NULL;
1066 interpreter_name = check_interpreter (name, fd, &extra);
1067 if (!interpreter_name)
1068 goto fail;
1069
1070
1071 if (interpreter_name != name)
1072 {
1073 close (fd);
1074 fd = open (interpreter_name, O_RDONLY);
1075 if (fd < 0)
1076 return NULL;
1077
1078
1079
1080
1081 if (insert_args (tracee, regs, interpreter_name,
1082 extra, name))
1083 goto fail1;
1084 }
1085
1086 rc = read (fd, &header, sizeof header);
1087
1088 if (rc < sizeof header)
1089 goto fail1;
1090
1091
1092
1093 if (header.e_ident[0] != 0x7f
1094 || header.e_ident[1] != 'E'
1095 || header.e_ident[2] != 'L'
1096 || header.e_ident[3] != 'F')
1097 goto fail1;
1098
1099
1100 #ifdef EXEC_64
1101 if (header.e_ident[4] != 2)
1102 goto fail1;
1103 #else
1104 if (header.e_ident[4] != 1)
1105 goto fail1;
1106 #endif
1107
1108
1109 #ifndef WORDS_BIGENDIAN
1110 if (header.e_ident[5] != 1)
1111 goto fail1;
1112 #else
1113 if (header.e_ident[5] != 2)
1114 goto fail1;
1115 #endif
1116
1117
1118 if (header.e_type != 2 && header.e_type != 3)
1119 goto fail1;
1120
1121
1122 if (header.e_phnum > 0xffff
1123 || (header.e_phentsize
1124 != sizeof (program_header)))
1125 goto fail1;
1126
1127
1128 rc = lseek (fd, header.e_phoff, SEEK_SET);
1129 if (rc < 0)
1130 goto fail1;
1131 loader_area_used = 0;
1132
1133
1134 if (write_open_command (interpreter_name, false))
1135 goto fail1;
1136
1137
1138
1139 if (header.e_type == 3)
1140 offset = EXECUTABLE_BASE;
1141 else
1142 offset = 0;
1143
1144
1145
1146
1147 entry = header.e_entry + offset;
1148 program_entry = header.e_entry;
1149
1150 #if defined __mips__ && !defined MIPS_NABI
1151
1152 exec_abiflags = NULL;
1153 interpreter_abiflags = NULL;
1154 interpreter_header = NULL;
1155 #endif
1156
1157
1158
1159 header_offset = -1;
1160
1161 for (i = 0; i < header.e_phnum; ++i)
1162 {
1163 rc = read (fd, &program, sizeof program);
1164 if (rc < sizeof program)
1165 goto fail1;
1166
1167 if (process_program_header (interpreter_name, fd,
1168 &program, &header,
1169 &entry, &header_offset))
1170 goto fail1;
1171 }
1172
1173
1174
1175 jump.command = 3;
1176 jump.entry = entry;
1177
1178
1179
1180 jump.at_entry = program_entry + offset;
1181 jump.at_phent = header.e_phentsize;
1182 jump.at_phnum = header.e_phnum;
1183 jump.at_base = (entry == header.e_entry + offset
1184 ? EXECUTABLE_BASE
1185 : INTERPRETER_BASE);
1186
1187 #if defined __mips__ && !defined MIPS_NABI
1188
1189
1190 if (determine_fpu_mode (&header, interpreter_header,
1191 &fpu_mode, exec_abiflags,
1192 interpreter_abiflags))
1193
1194 goto fail;
1195
1196
1197
1198
1199 if (fpu_mode == FP_FR0 && !cpu_supports_fr0_p ())
1200 fpu_mode = FP_FRE;
1201
1202 jump.fpu_mode = fpu_mode;
1203 #endif
1204
1205
1206
1207
1208 if (header_offset == (USER_WORD) -1)
1209 header_offset = 0;
1210
1211 jump.at_phdr = header.e_phoff + header_offset;
1212
1213 if (sizeof loader_area - loader_area_used < sizeof jump)
1214 goto fail1;
1215
1216 memcpy (loader_area + loader_area_used, &jump,
1217 sizeof jump);
1218 loader_area_used += sizeof jump;
1219
1220
1221
1222
1223 close (fd);
1224 *size = loader_area_used;
1225
1226
1227 assert (!(loader_area_used & (sizeof (USER_WORD) - 1)));
1228 return loader_area;
1229
1230 fail1:
1231 errno = ENOEXEC;
1232 fail:
1233 close (fd);
1234 return NULL;
1235 }