blob: c0bdb0a8b10461954848ba17d2408401ee0114fd [file] [log] [blame]
jseward2886b0e2004-01-04 03:46:11 +00001
nethercotebb1c9912004-01-04 16:43:23 +00002/*--------------------------------------------------------------------*/
3/*--- User-mode execve() ume.c ---*/
4/*--------------------------------------------------------------------*/
5
jseward2886b0e2004-01-04 03:46:11 +00006/*
7 This file is part of Valgrind, an extensible x86 protected-mode
8 emulator for monitoring program execution on x86-Unixes.
9
10 Copyright (C) 2000-2004 Julian Seward
11 jseward@acm.org
12
13 This program is free software; you can redistribute it and/or
14 modify it under the terms of the GNU General Public License as
15 published by the Free Software Foundation; either version 2 of the
16 License, or (at your option) any later version.
17
18 This program is distributed in the hope that it will be useful, but
19 WITHOUT ANY WARRANTY; without even the implied warranty of
20 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
21 General Public License for more details.
22
23 You should have received a copy of the GNU General Public License
24 along with this program; if not, write to the Free Software
25 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
26 02111-1307, USA.
27
28 The GNU General Public License is contained in the file COPYING.
29*/
30
fitzhardinge7e343cd2003-12-16 02:14:00 +000031
32#define _GNU_SOURCE
33#define _FILE_OFFSET_BITS 64
34
35#include "vg_include.h"
36
37#include <stddef.h>
38#include <sys/mman.h>
39#include <fcntl.h>
40#include <errno.h>
41#include <elf.h>
42#include <stdio.h>
43#include <string.h>
44#include <stdlib.h>
45#include <unistd.h>
fitzhardinge7e343cd2003-12-16 02:14:00 +000046#include <sys/stat.h>
fitzhardinge7e343cd2003-12-16 02:14:00 +000047#include <dlfcn.h>
48#include <assert.h>
49
50#include "ume.h"
fitzhardingeb50068f2004-02-24 23:42:55 +000051#include "vg_include.h"
fitzhardinge7e343cd2003-12-16 02:14:00 +000052
nethercote1fe54502004-07-26 15:28:33 +000053struct elfinfo
54{
55 ESZ(Ehdr) e;
56 ESZ(Phdr) *p;
57 int fd;
58};
59
fitzhardinge7e343cd2003-12-16 02:14:00 +000060static int padfile = -1;
61static struct stat padstat;
62
63extern int kickstart_base; /* linker created */
64
nethercote30d37842004-07-26 10:05:55 +000065static void check_mmap(void* res, void* base, int len)
nethercotebfed1c82004-07-17 12:57:44 +000066{
67 if ((void*)-1 == res) {
68 fprintf(stderr, "valgrind: mmap(%p, %d) failed during startup.\n"
69 "valgrind: is there a hard virtual memory limit set?\n",
70 base, len);
71 exit(1);
72 }
73}
74
fitzhardinge7e343cd2003-12-16 02:14:00 +000075void foreach_map(int (*fn)(void *start, void *end,
76 const char *perm, off_t offset,
77 int maj, int min, int ino))
78{
79 static char buf[10240];
80 char *bufptr = buf;
81 int ret, fd;
82
83 fd = open("/proc/self/maps", O_RDONLY);
84
85 if (fd == -1) {
86 perror("open /proc/self/maps");
87 return;
88 }
89
90 ret = read(fd, buf, sizeof(buf));
91
92 if (ret == -1) {
93 perror("read /proc/self/maps");
94 close(fd);
95 return;
96 }
97 close(fd);
98
99 if (ret == sizeof(buf)) {
100 fprintf(stderr, "buf too small\n");
101 return;
102 }
103
104 while(bufptr && bufptr < buf+ret) {
105 char perm[5];
106 off_t offset;
107 int maj, min;
108 int ino;
109 void *segstart, *segend;
110
111 sscanf(bufptr, "%p-%p %s %Lx %x:%x %d",
112 &segstart, &segend, perm, &offset, &maj, &min, &ino);
113 bufptr = strchr(bufptr, '\n');
114 if (bufptr != NULL)
115 bufptr++; /* skip \n */
116
117 if (!(*fn)(segstart, segend, perm, offset, maj, min, ino))
118 break;
119 }
120}
121
thughes4ad52d02004-06-27 17:37:21 +0000122static char *fillgap_addr;
123static char *fillgap_end;
124
125static int fillgap(void *segstart, void *segend, const char *perm, off_t off,
126 int maj, int min, int ino) {
127 if ((char *)segstart >= fillgap_end)
128 return 0;
129
nethercotebfed1c82004-07-17 12:57:44 +0000130 if ((char *)segstart > fillgap_addr) {
131 void* res = mmap(fillgap_addr, (char *)segstart-fillgap_addr, PROT_NONE,
132 MAP_FIXED|MAP_PRIVATE, padfile, 0);
133 check_mmap(res, fillgap_addr, (char*)segstart - fillgap_addr);
134 }
thughes4ad52d02004-06-27 17:37:21 +0000135 fillgap_addr = segend;
136
137 return 1;
138}
139
fitzhardinge7e343cd2003-12-16 02:14:00 +0000140/* pad all the empty spaces in a range of address space to stop
141 interlopers */
142void as_pad(void *start, void *end)
143{
144 char buf[1024];
fitzhardinge7e343cd2003-12-16 02:14:00 +0000145
146 if (padfile == -1) {
147 int seq = 1;
148 do {
149 sprintf(buf, "/tmp/.pad.%d.%d", getpid(), seq++);
150 padfile = open(buf, O_RDWR|O_CREAT|O_EXCL, 0);
151 unlink(buf);
152 if (padfile == -1 && errno != EEXIST)
153 exit(44);
154 } while(padfile == -1);
155 fstat(padfile, &padstat);
156 }
157
thughes4ad52d02004-06-27 17:37:21 +0000158 fillgap_addr = start;
159 fillgap_end = end;
fitzhardinge7e343cd2003-12-16 02:14:00 +0000160
161 foreach_map(fillgap);
162
nethercotebfed1c82004-07-17 12:57:44 +0000163 if (fillgap_addr < fillgap_end) {
164 void* res = mmap(fillgap_addr, fillgap_end-fillgap_addr, PROT_NONE,
165 MAP_FIXED|MAP_PRIVATE, padfile, 0);
166 check_mmap(res, fillgap_addr, fillgap_end - fillgap_addr);
167 }
thughes4ad52d02004-06-27 17:37:21 +0000168}
169
170static void *killpad_start;
171static void *killpad_end;
172
173static int killpad(void *segstart, void *segend, const char *perm, off_t off,
nethercotebfed1c82004-07-17 12:57:44 +0000174 int maj, int min, int ino)
175{
thughes4ad52d02004-06-27 17:37:21 +0000176 void *b, *e;
nethercotebfed1c82004-07-17 12:57:44 +0000177 int res;
thughes4ad52d02004-06-27 17:37:21 +0000178
179 if (padstat.st_dev != makedev(maj, min) || padstat.st_ino != ino)
180 return 1;
181
182 if (segend <= killpad_start || segstart >= killpad_end)
183 return 1;
184
185 if (segstart <= killpad_start)
186 b = killpad_start;
187 else
188 b = segstart;
189
190 if (segend >= killpad_end)
191 e = killpad_end;
192 else
193 e = segend;
194
nethercotebfed1c82004-07-17 12:57:44 +0000195 res = munmap(b, (char *)e-(char *)b);
196 assert(0 == res);
thughes4ad52d02004-06-27 17:37:21 +0000197
198 return 1;
fitzhardinge7e343cd2003-12-16 02:14:00 +0000199}
200
201/* remove padding from a range of address space - padding is always a
202 mapping of padfile*/
203void as_unpad(void *start, void *end)
204{
fitzhardinge7e343cd2003-12-16 02:14:00 +0000205 if (padfile == -1) /* no padfile, no padding */
206 return;
thughes4ad52d02004-06-27 17:37:21 +0000207
208 killpad_start = start;
209 killpad_end = end;
210
fitzhardinge7e343cd2003-12-16 02:14:00 +0000211 foreach_map(killpad);
212}
213
214void as_closepadfile(void)
215{
216 /* don't unpad */
217 close(padfile);
218 padfile = -1;
219}
220
221int as_getpadfd(void)
222{
223 return padfile;
224}
225
226void as_setpadfd(int fd)
227{
228 as_closepadfile();
229 padfile = fd;
230 fstat(padfile, &padstat);
231}
232
233struct ume_auxv *find_auxv(int *esp)
234{
235 esp++; /* skip argc */
236
237 while(*esp != 0) /* skip argv */
238 esp++;
239 esp++;
240
241 while(*esp != 0) /* skip env */
242 esp++;
243 esp++;
244
245 return (struct ume_auxv *)esp;
246}
247
248
249struct elfinfo *readelf(int fd, const char *filename)
250{
251 struct elfinfo *e = malloc(sizeof(*e));
252 int phsz;
253
nethercote7c018f42004-07-17 16:40:50 +0000254 assert(e);
fitzhardinge7e343cd2003-12-16 02:14:00 +0000255 e->fd = fd;
256
257 if (pread(fd, &e->e, sizeof(e->e), 0) != sizeof(e->e)) {
nethercote08eaff32004-07-22 12:41:12 +0000258 fprintf(stderr, "valgrind: %s: can't read elf header: %s\n",
fitzhardinge7e343cd2003-12-16 02:14:00 +0000259 filename, strerror(errno));
260 return NULL;
261 }
262
263 if (memcmp(&e->e.e_ident[0], ELFMAG, SELFMAG) != 0) {
nethercote08eaff32004-07-22 12:41:12 +0000264 fprintf(stderr, "valgrind: %s: bad ELF magic\n", filename);
fitzhardinge7e343cd2003-12-16 02:14:00 +0000265 return NULL;
266 }
267 if (e->e.e_ident[EI_CLASS] != ELFCLASS32) {
nethercote08eaff32004-07-22 12:41:12 +0000268 fprintf(stderr, "valgrind: Can only handle 32-bit executables\n");
fitzhardinge7e343cd2003-12-16 02:14:00 +0000269 return NULL;
270 }
271 if (e->e.e_ident[EI_DATA] != ELFDATA2LSB) {
nethercote08eaff32004-07-22 12:41:12 +0000272 fprintf(stderr, "valgrind: Expecting little-endian\n");
fitzhardinge7e343cd2003-12-16 02:14:00 +0000273 return NULL;
274 }
275 if (!(e->e.e_type == ET_EXEC || e->e.e_type == ET_DYN)) {
nethercote08eaff32004-07-22 12:41:12 +0000276 fprintf(stderr, "valgrind: need executable\n");
fitzhardinge7e343cd2003-12-16 02:14:00 +0000277 return NULL;
278 }
279
280 if (e->e.e_machine != EM_386) {
nethercote08eaff32004-07-22 12:41:12 +0000281 fprintf(stderr, "valgrind: need x86\n");
fitzhardinge7e343cd2003-12-16 02:14:00 +0000282 return NULL;
283 }
284
285 if (e->e.e_phentsize != sizeof(ESZ(Phdr))) {
nethercote08eaff32004-07-22 12:41:12 +0000286 fprintf(stderr, "valgrind: sizeof Phdr wrong\n");
fitzhardinge7e343cd2003-12-16 02:14:00 +0000287 return NULL;
288 }
289
290 phsz = sizeof(ESZ(Phdr)) * e->e.e_phnum;
291 e->p = malloc(phsz);
nethercote7c018f42004-07-17 16:40:50 +0000292 assert(e->p);
fitzhardinge7e343cd2003-12-16 02:14:00 +0000293
294 if (pread(fd, e->p, phsz, e->e.e_phoff) != phsz) {
nethercote08eaff32004-07-22 12:41:12 +0000295 fprintf(stderr, "valgrind: can't read phdr: %s\n", strerror(errno));
fitzhardinge7e343cd2003-12-16 02:14:00 +0000296 return NULL;
297 }
298
299 return e;
300}
301
302#define REMAINS(x, a) ((x) & ((a)-1))
303
304/* Map an ELF file. Returns the brk address. */
fitzhardingeb50068f2004-02-24 23:42:55 +0000305ESZ(Addr) mapelf(struct elfinfo *e, ESZ(Addr) base)
fitzhardinge7e343cd2003-12-16 02:14:00 +0000306{
307 int i;
nethercotebfed1c82004-07-17 12:57:44 +0000308 void* res;
fitzhardinge7e343cd2003-12-16 02:14:00 +0000309 ESZ(Addr) elfbrk = 0;
310
311 for(i = 0; i < e->e.e_phnum; i++) {
312 ESZ(Phdr) *ph = &e->p[i];
313 ESZ(Addr) addr, brkaddr;
314 ESZ(Word) memsz;
315
316 if (ph->p_type != PT_LOAD)
317 continue;
318
319 addr = ph->p_vaddr+base;
320 memsz = ph->p_memsz;
321 brkaddr = addr+memsz;
322
323 if (brkaddr > elfbrk)
324 elfbrk = brkaddr;
325 }
326
fitzhardinge7e343cd2003-12-16 02:14:00 +0000327 for(i = 0; i < e->e.e_phnum; i++) {
328 ESZ(Phdr) *ph = &e->p[i];
329 ESZ(Addr) addr, bss, brkaddr;
330 ESZ(Off) off;
331 ESZ(Word) filesz;
332 ESZ(Word) memsz;
333 ESZ(Word) align;
334 unsigned prot = 0;
335
336 if (ph->p_type != PT_LOAD)
337 continue;
338
339 if (ph->p_flags & PF_X)
340 prot |= PROT_EXEC;
341 if (ph->p_flags & PF_W)
342 prot |= PROT_WRITE;
343 if (ph->p_flags & PF_R)
344 prot |= PROT_READ;
345
346 align = ph->p_align;
347
348 addr = ph->p_vaddr+base;
349 off = ph->p_offset;
350 filesz = ph->p_filesz;
351 bss = addr+filesz;
352 memsz = ph->p_memsz;
353 brkaddr = addr+memsz;
354
nethercotebfed1c82004-07-17 12:57:44 +0000355 res = mmap((char *)ROUNDDN(addr, align),
356 ROUNDUP(bss, align)-ROUNDDN(addr, align),
357 prot, MAP_FIXED|MAP_PRIVATE, e->fd, ROUNDDN(off, align));
358 check_mmap(res, (char*)ROUNDDN(addr,align),
359 ROUNDUP(bss, align)-ROUNDDN(addr, align));
fitzhardinge7e343cd2003-12-16 02:14:00 +0000360
361 /* if memsz > filesz, then we need to fill the remainder with zeroed pages */
362 if (memsz > filesz) {
363 UInt bytes;
364
365 bytes = ROUNDUP(brkaddr, align)-ROUNDUP(bss, align);
nethercotebfed1c82004-07-17 12:57:44 +0000366 if (bytes > 0) {
367 res = mmap((char *)ROUNDUP(bss, align), bytes,
368 prot, MAP_FIXED|MAP_ANONYMOUS|MAP_PRIVATE, -1, 0);
369 check_mmap(res, (char*)ROUNDUP(bss,align), bytes);
370 }
fitzhardinge7e343cd2003-12-16 02:14:00 +0000371
372 bytes = bss & (VKI_BYTES_PER_PAGE - 1);
373 if (bytes > 0) {
374 bytes = VKI_BYTES_PER_PAGE - bytes;
375 memset((char *)bss, 0, bytes);
376 }
377 }
378 }
379
380 return elfbrk;
381}
382
383
384static int do_exec_inner(const char *exe, struct exeinfo *info);
385
386
387static int match_ELF(const char *hdr, int len)
388{
389 ESZ(Ehdr) *e = (ESZ(Ehdr) *)hdr;
390 return (len > sizeof(*e)) && memcmp(&e->e_ident[0], ELFMAG, SELFMAG) == 0;
391}
392
393static int load_ELF(char *hdr, int len, int fd, const char *name, struct exeinfo *info)
394{
395 struct elfinfo *e;
396 struct elfinfo *interp = NULL;
397 ESZ(Addr) minaddr = ~0;
398 ESZ(Addr) maxaddr = 0;
399 ESZ(Addr) interp_addr = 0;
400 ESZ(Word) interp_size = 0;
401 int i;
402 void *entry;
403
404 e = readelf(fd, name);
405
406 if (e == NULL)
407 return ENOEXEC;
408
409 info->phnum = e->e.e_phnum;
410 info->entry = e->e.e_entry;
411
412 for(i = 0; i < e->e.e_phnum; i++) {
413 ESZ(Phdr) *ph = &e->p[i];
414
415 switch(ph->p_type) {
416 case PT_PHDR:
417 info->phdr = ph->p_vaddr;
418 break;
419
420 case PT_LOAD:
421 if (ph->p_vaddr < minaddr)
422 minaddr = ph->p_vaddr;
423 if (ph->p_vaddr+ph->p_memsz > maxaddr)
424 maxaddr = ph->p_vaddr+ph->p_memsz;
425 break;
426
427 case PT_INTERP: {
428 char *buf = malloc(ph->p_filesz+1);
429 int j;
430 int intfd;
431 int baseaddr_set;
432
nethercote7c018f42004-07-17 16:40:50 +0000433 assert(buf);
fitzhardinge7e343cd2003-12-16 02:14:00 +0000434 pread(fd, buf, ph->p_filesz, ph->p_offset);
435 buf[ph->p_filesz] = '\0';
436
437 intfd = open(buf, O_RDONLY);
438 if (intfd == -1) {
439 perror("open interp");
440 exit(1);
441 }
442
443 interp = readelf(intfd, buf);
444 if (interp == NULL) {
445 fprintf(stderr, "Can't read interpreter\n");
446 return 1;
447 }
448 free(buf);
449
450 baseaddr_set = 0;
451 for(j = 0; j < interp->e.e_phnum; j++) {
452 ESZ(Phdr) *iph = &interp->p[j];
453 ESZ(Addr) end;
454
455 if (iph->p_type != PT_LOAD)
456 continue;
457
458 if (!baseaddr_set) {
459 interp_addr = iph->p_vaddr;
460 baseaddr_set = 1;
461 }
462
463 /* assumes that all segments in the interp are close */
464 end = (iph->p_vaddr - interp_addr) + iph->p_memsz;
465
466 if (end > interp_size)
467 interp_size = end;
468 }
469 break;
470 }
471 }
472 }
473
474 if (info->exe_base != info->exe_end) {
475 if (minaddr >= maxaddr ||
476 (minaddr < info->exe_base ||
477 maxaddr > info->exe_end)) {
478 fprintf(stderr, "Executable is mapped outside of range %p-%p\n",
479 (void *)info->exe_base, (void *)info->exe_end);
480 return ENOMEM;
481 }
482 }
483
fitzhardingeb50068f2004-02-24 23:42:55 +0000484 info->brkbase = mapelf(e, 0); /* map the executable */
fitzhardinge7e343cd2003-12-16 02:14:00 +0000485
fitzhardinge92360792003-12-24 10:11:11 +0000486 if (info->brkbase == 0)
487 return ENOMEM;
488
fitzhardinge7e343cd2003-12-16 02:14:00 +0000489 if (interp != NULL) {
490 /* reserve a chunk of address space for interpreter */
nethercotebfed1c82004-07-17 12:57:44 +0000491 void* res;
492 char* base = (char *)info->exe_base;
493 char* baseoff;
fitzhardinge7e343cd2003-12-16 02:14:00 +0000494 int flags = MAP_PRIVATE|MAP_ANONYMOUS;
495
496 if (info->map_base != 0) {
497 base = (char *)info->map_base;
498 flags |= MAP_FIXED;
499 }
500
nethercotebfed1c82004-07-17 12:57:44 +0000501 res = mmap(base, interp_size, PROT_NONE, flags, -1, 0);
502 check_mmap(res, base, interp_size);
503 base = res;
fitzhardinge7e343cd2003-12-16 02:14:00 +0000504
505 baseoff = base - interp_addr;
506
fitzhardingeb50068f2004-02-24 23:42:55 +0000507 mapelf(interp, (ESZ(Addr))baseoff);
fitzhardinge7e343cd2003-12-16 02:14:00 +0000508
509 close(interp->fd);
510 free(interp);
511
512 entry = baseoff + interp->e.e_entry;
513 info->interp_base = (ESZ(Addr))base;
514 } else
515 entry = (void *)e->e.e_entry;
516
517 info->exe_base = minaddr;
518 info->exe_end = maxaddr;
519
520 info->init_eip = (addr_t)entry;
521
522 free(e);
523
524 return 0;
525}
526
527
528static int match_script(const char *hdr, Int len)
529{
530 return (len > 2) && memcmp(hdr, "#!", 2) == 0;
531}
532
533static int load_script(char *hdr, int len, int fd, const char *name, struct exeinfo *info)
534{
535 char *interp;
536 char *const end = hdr+len;
537 char *cp;
538 char *arg = NULL;
539 int eol;
540
541 interp = hdr + 2;
542 while(interp < end && (*interp == ' ' || *interp == '\t'))
543 interp++;
544
545 if (*interp != '/')
546 return ENOEXEC; /* absolute path only for interpreter */
547
548 /* skip over interpreter name */
549 for(cp = interp; cp < end && *cp != ' ' && *cp != '\t' && *cp != '\n'; cp++)
550 ;
551
552 eol = (*cp == '\n');
553
554 *cp++ = '\0';
555
556 if (!eol && cp < end) {
557 /* skip space before arg */
558 while (cp < end && (*cp == '\t' || *cp == ' '))
559 cp++;
560
561 /* arg is from here to eol */
562 arg = cp;
563 while (cp < end && *cp != '\n')
564 cp++;
565 *cp = '\0';
566 }
567
nethercoted6a56872004-07-26 15:32:47 +0000568 info->interp_name = strdup(interp);
569 assert(NULL != info->interp_name);
nethercote71980f02004-01-24 18:18:54 +0000570 if (arg != NULL && *arg != '\0') {
nethercoted6a56872004-07-26 15:32:47 +0000571 info->interp_args = strdup(arg);
572 assert(NULL != info->interp_args);
nethercote71980f02004-01-24 18:18:54 +0000573 }
fitzhardinge7e343cd2003-12-16 02:14:00 +0000574
575 if (info->argv && info->argv[0] != NULL)
576 info->argv[0] = (char *)name;
577
578 if (0)
nethercoted6a56872004-07-26 15:32:47 +0000579 printf("#! script: interp_name=\"%s\" interp_args=\"%s\"\n",
580 info->interp_name, info->interp_args);
fitzhardinge7e343cd2003-12-16 02:14:00 +0000581
582 return do_exec_inner(interp, info);
583}
584
585struct binfmt {
586 int (*match)(const char *hdr, int len);
587 int (*load) ( char *hdr, int len, int fd, const char *name, struct exeinfo *);
588};
589
590static const struct binfmt formats[] = {
591 { match_ELF, load_ELF },
592 { match_script, load_script },
593};
594
595
596static int do_exec_inner(const char *exe, struct exeinfo *info)
597{
598 int fd;
599 char buf[VKI_BYTES_PER_PAGE];
600 int bufsz;
601 int i;
602 int ret;
603 struct stat st;
604
605 fd = open(exe, O_RDONLY);
606 if (fd == -1) {
607 if (0)
608 fprintf(stderr, "Can't open executable %s: %s\n",
609 exe, strerror(errno));
610 return errno;
611 }
612
613 if (fstat(fd, &st) == -1)
614 return errno;
615 else {
616 uid_t uid = geteuid();
617 gid_t gid = getegid();
618 gid_t groups[32];
619 int ngrp = getgroups(32, groups);
620
fitzhardingea49f9b52003-12-16 22:26:45 +0000621 if (st.st_mode & (S_ISUID | S_ISGID)) {
622 fprintf(stderr, "Can't execute suid/sgid executable %s\n", exe);
623 return EACCES;
624 }
625
fitzhardinge6d5dafa2004-01-04 23:10:07 +0000626 if (uid == st.st_uid) {
627 if (!(st.st_mode & S_IXUSR))
fitzhardinge7e343cd2003-12-16 02:14:00 +0000628 return EACCES;
fitzhardinge6d5dafa2004-01-04 23:10:07 +0000629 } else {
630 int grpmatch = 0;
fitzhardinge7e343cd2003-12-16 02:14:00 +0000631
fitzhardinge6d5dafa2004-01-04 23:10:07 +0000632 if (gid == st.st_gid)
633 grpmatch = 1;
634 else
635 for(i = 0; i < ngrp; i++)
636 if (groups[i] == st.st_gid) {
637 grpmatch = 1;
638 break;
639 }
640
641 if (grpmatch) {
642 if (!(st.st_mode & S_IXGRP))
643 return EACCES;
644 } else if (!(st.st_mode & S_IXOTH))
645 return EACCES;
646 }
fitzhardinge7e343cd2003-12-16 02:14:00 +0000647 }
648
649 bufsz = pread(fd, buf, sizeof(buf), 0);
650 if (bufsz < 0) {
651 fprintf(stderr, "Can't read executable header: %s\n",
652 strerror(errno));
653 close(fd);
654 return errno;
655 }
656
657 ret = ENOEXEC;
658 for(i = 0; i < sizeof(formats)/sizeof(*formats); i++) {
659 if ((formats[i].match)(buf, bufsz)) {
660 ret = (formats[i].load)(buf, bufsz, fd, exe, info);
661 break;
662 }
663 }
664
665 close(fd);
666
667 return ret;
668}
669
670int do_exec(const char *exe, struct exeinfo *info)
671{
nethercoted6a56872004-07-26 15:32:47 +0000672 info->interp_name = NULL;
673 info->interp_args = NULL;
fitzhardinge7e343cd2003-12-16 02:14:00 +0000674
675 return do_exec_inner(exe, info);
676}
nethercotebb1c9912004-01-04 16:43:23 +0000677
678/*--------------------------------------------------------------------*/
679/*--- end ume.c ---*/
680/*--------------------------------------------------------------------*/