blob: 93d79a9a434686a79f1a5fb13bf0ebc16a91f322 [file] [log] [blame]
jseward2886b0e2004-01-04 03:46:11 +00001
nethercotebb1c9912004-01-04 16:43:23 +00002/*--------------------------------------------------------------------*/
nethercote107e1c02004-10-13 17:55:31 +00003/*--- User-mode execve(), and other stuff shared between stage1 ---*/
njn08a2e172005-06-21 22:47:54 +00004/*--- and stage2. m_ume.c ---*/
nethercotebb1c9912004-01-04 16:43:23 +00005/*--------------------------------------------------------------------*/
6
jseward2886b0e2004-01-04 03:46:11 +00007/*
njnb9c427c2004-12-01 14:14:42 +00008 This file is part of Valgrind, a dynamic binary instrumentation
9 framework.
jseward2886b0e2004-01-04 03:46:11 +000010
sewardj4d474d02008-02-11 11:34:59 +000011 Copyright (C) 2000-2008 Julian Seward
jseward2886b0e2004-01-04 03:46:11 +000012 jseward@acm.org
13
14 This program is free software; you can redistribute it and/or
15 modify it under the terms of the GNU General Public License as
16 published by the Free Software Foundation; either version 2 of the
17 License, or (at your option) any later version.
18
19 This program is distributed in the hope that it will be useful, but
20 WITHOUT ANY WARRANTY; without even the implied warranty of
21 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
22 General Public License for more details.
23
24 You should have received a copy of the GNU General Public License
25 along with this program; if not, write to the Free Software
26 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
27 02111-1307, USA.
28
29 The GNU General Public License is contained in the file COPYING.
30*/
31
fitzhardinge7e343cd2003-12-16 02:14:00 +000032
sewardj4b0c0712005-06-19 15:58:33 +000033#include "pub_core_basics.h"
sewardj4cfea4f2006-10-14 19:26:10 +000034#include "pub_core_vki.h"
sewardjec7be9c2006-10-17 01:59:30 +000035
36#if defined(VGO_linux)
37
njn73750612005-10-14 03:11:30 +000038#include "pub_core_aspacemgr.h" // various mapping fns
sewardj45f4e7c2005-09-27 19:20:21 +000039#include "pub_core_debuglog.h"
sewardj4b0c0712005-06-19 15:58:33 +000040#include "pub_core_libcbase.h"
41#include "pub_core_machine.h"
sewardj45f4e7c2005-09-27 19:20:21 +000042#include "pub_core_libcprint.h"
43#include "pub_core_libcfile.h" // VG_(close) et al
44#include "pub_core_libcproc.h" // VG_(geteuid), VG_(getegid)
45#include "pub_core_libcassert.h" // VG_(exit), vg_assert
sewardj45f4e7c2005-09-27 19:20:21 +000046#include "pub_core_mallocfree.h" // VG_(malloc), VG_(free)
njn73750612005-10-14 03:11:30 +000047#include "pub_core_syscall.h" // VG_(strerror)
sewardjc74b3ba2007-11-17 21:11:57 +000048#include "pub_core_options.h" // VG_(clo_xml)
sewardjec7be9c2006-10-17 01:59:30 +000049#include "pub_core_ume.h" // self
sewardj45f4e7c2005-09-27 19:20:21 +000050
sewardjec7be9c2006-10-17 01:59:30 +000051/* --- !!! --- EXTERNAL HEADERS start --- !!! --- */
52#define _GNU_SOURCE
53#define _FILE_OFFSET_BITS 64
54/* This is for ELF types etc, and also the AT_ constants. */
55#include <elf.h>
56/* --- !!! --- EXTERNAL HEADERS end --- !!! --- */
sewardj4b0c0712005-06-19 15:58:33 +000057
fitzhardinge7e343cd2003-12-16 02:14:00 +000058
sewardjfbd78b22005-06-19 16:14:06 +000059#if VG_WORDSIZE == 8
nethercote3f458152004-11-01 18:42:23 +000060#define ESZ(x) Elf64_##x
sewardjfbd78b22005-06-19 16:14:06 +000061#elif VG_WORDSIZE == 4
nethercote3f458152004-11-01 18:42:23 +000062#define ESZ(x) Elf32_##x
63#else
sewardjfbd78b22005-06-19 16:14:06 +000064#error VG_WORDSIZE needs to ==4 or ==8
nethercote3f458152004-11-01 18:42:23 +000065#endif
66
nethercote1fe54502004-07-26 15:28:33 +000067struct elfinfo
68{
69 ESZ(Ehdr) e;
70 ESZ(Phdr) *p;
njn73750612005-10-14 03:11:30 +000071 Int fd;
nethercote1fe54502004-07-26 15:28:33 +000072};
73
sewardj45f4e7c2005-09-27 19:20:21 +000074static void check_mmap(SysRes res, Addr base, SizeT len)
nethercotebfed1c82004-07-17 12:57:44 +000075{
sewardj45f4e7c2005-09-27 19:20:21 +000076 if (res.isError) {
sewardj26406b12006-12-01 18:48:56 +000077 VG_(printf)("valgrind: mmap(0x%llx, %lld) failed in UME "
njn8a7b41b2007-09-23 00:51:24 +000078 "with error %lu (%s).\n",
sewardj26406b12006-12-01 18:48:56 +000079 (ULong)base, (Long)len,
80 res.err, VG_(strerror)(res.err) );
sewardj2f80d132006-12-27 05:18:33 +000081 if (res.err == VKI_EINVAL) {
82 VG_(printf)("valgrind: this can be caused by executables with "
83 "very large text, data or bss segments.\n");
84 }
sewardj45f4e7c2005-09-27 19:20:21 +000085 VG_(exit)(1);
nethercotebfed1c82004-07-17 12:57:44 +000086 }
87}
88
njnfcb7c3e2005-06-18 15:54:25 +000089/*------------------------------------------------------------*/
nethercote31779c72004-07-30 21:50:15 +000090/*--- Finding auxv on the stack ---*/
91/*------------------------------------------------------------*/
fitzhardinge7e343cd2003-12-16 02:14:00 +000092
njn62ff0f22005-06-21 23:03:36 +000093struct ume_auxv *VG_(find_auxv)(UWord* sp)
fitzhardinge7e343cd2003-12-16 02:14:00 +000094{
nethercoteebf1d862004-11-01 18:22:05 +000095 sp++; // skip argc (Nb: is word-sized, not int-sized!)
fitzhardinge7e343cd2003-12-16 02:14:00 +000096
nethercoteebf1d862004-11-01 18:22:05 +000097 while (*sp != 0) // skip argv
98 sp++;
99 sp++;
fitzhardinge7e343cd2003-12-16 02:14:00 +0000100
nethercoteebf1d862004-11-01 18:22:05 +0000101 while (*sp != 0) // skip env
102 sp++;
103 sp++;
fitzhardinge7e343cd2003-12-16 02:14:00 +0000104
sewardj13247ca2005-12-30 22:52:20 +0000105#if defined(VGA_ppc32) || defined(VGA_ppc64)
cerion85665ca2005-06-20 15:51:07 +0000106# if defined AT_IGNOREPPC
107 while (*sp == AT_IGNOREPPC) // skip AT_IGNOREPPC entries
108 sp += 2;
109# endif
110#endif
111
nethercoteebf1d862004-11-01 18:22:05 +0000112 return (struct ume_auxv *)sp;
fitzhardinge7e343cd2003-12-16 02:14:00 +0000113}
114
nethercote31779c72004-07-30 21:50:15 +0000115/*------------------------------------------------------------*/
116/*--- Loading ELF files ---*/
117/*------------------------------------------------------------*/
fitzhardinge7e343cd2003-12-16 02:14:00 +0000118
sewardj2c5ffbe2005-03-12 13:32:06 +0000119static
njn73750612005-10-14 03:11:30 +0000120struct elfinfo *readelf(Int fd, const char *filename)
fitzhardinge7e343cd2003-12-16 02:14:00 +0000121{
sewardj45f4e7c2005-09-27 19:20:21 +0000122 SysRes sres;
sewardj9c606bd2008-09-18 18:12:50 +0000123 struct elfinfo *e = VG_(malloc)("ume.re.1", sizeof(*e));
njn73750612005-10-14 03:11:30 +0000124 Int phsz;
fitzhardinge7e343cd2003-12-16 02:14:00 +0000125
sewardj45f4e7c2005-09-27 19:20:21 +0000126 vg_assert(e);
fitzhardinge7e343cd2003-12-16 02:14:00 +0000127 e->fd = fd;
128
sewardj45f4e7c2005-09-27 19:20:21 +0000129 sres = VG_(pread)(fd, &e->e, sizeof(e->e), 0);
sewardjec7be9c2006-10-17 01:59:30 +0000130 if (sres.isError || sres.res != sizeof(e->e)) {
sewardj45f4e7c2005-09-27 19:20:21 +0000131 VG_(printf)("valgrind: %s: can't read ELF header: %s\n",
sewardjec7be9c2006-10-17 01:59:30 +0000132 filename, VG_(strerror)(sres.err));
njn12f266f2005-06-28 19:20:46 +0000133 goto bad;
fitzhardinge7e343cd2003-12-16 02:14:00 +0000134 }
135
sewardj45f4e7c2005-09-27 19:20:21 +0000136 if (VG_(memcmp)(&e->e.e_ident[0], ELFMAG, SELFMAG) != 0) {
137 VG_(printf)("valgrind: %s: bad ELF magic number\n", filename);
njn12f266f2005-06-28 19:20:46 +0000138 goto bad;
fitzhardinge7e343cd2003-12-16 02:14:00 +0000139 }
njnaf839f52005-06-23 03:27:57 +0000140 if (e->e.e_ident[EI_CLASS] != VG_ELF_CLASS) {
sewardj45f4e7c2005-09-27 19:20:21 +0000141 VG_(printf)("valgrind: wrong ELF executable class "
142 "(eg. 32-bit instead of 64-bit)\n");
njn12f266f2005-06-28 19:20:46 +0000143 goto bad;
fitzhardinge7e343cd2003-12-16 02:14:00 +0000144 }
sewardj6e340c72005-07-10 00:53:42 +0000145 if (e->e.e_ident[EI_DATA] != VG_ELF_DATA2XXX) {
sewardj45f4e7c2005-09-27 19:20:21 +0000146 VG_(printf)("valgrind: executable has wrong endian-ness\n");
njn12f266f2005-06-28 19:20:46 +0000147 goto bad;
fitzhardinge7e343cd2003-12-16 02:14:00 +0000148 }
149 if (!(e->e.e_type == ET_EXEC || e->e.e_type == ET_DYN)) {
sewardj45f4e7c2005-09-27 19:20:21 +0000150 VG_(printf)("valgrind: this is not an executable\n");
njn12f266f2005-06-28 19:20:46 +0000151 goto bad;
fitzhardinge7e343cd2003-12-16 02:14:00 +0000152 }
153
njnaf839f52005-06-23 03:27:57 +0000154 if (e->e.e_machine != VG_ELF_MACHINE) {
sewardj45f4e7c2005-09-27 19:20:21 +0000155 VG_(printf)("valgrind: executable is not for "
156 "this architecture\n");
njn12f266f2005-06-28 19:20:46 +0000157 goto bad;
fitzhardinge7e343cd2003-12-16 02:14:00 +0000158 }
159
160 if (e->e.e_phentsize != sizeof(ESZ(Phdr))) {
sewardj45f4e7c2005-09-27 19:20:21 +0000161 VG_(printf)("valgrind: sizeof ELF Phdr wrong\n");
njn12f266f2005-06-28 19:20:46 +0000162 goto bad;
fitzhardinge7e343cd2003-12-16 02:14:00 +0000163 }
164
165 phsz = sizeof(ESZ(Phdr)) * e->e.e_phnum;
sewardj9c606bd2008-09-18 18:12:50 +0000166 e->p = VG_(malloc)("ume.re.2", phsz);
sewardj45f4e7c2005-09-27 19:20:21 +0000167 vg_assert(e->p);
fitzhardinge7e343cd2003-12-16 02:14:00 +0000168
sewardj45f4e7c2005-09-27 19:20:21 +0000169 sres = VG_(pread)(fd, e->p, phsz, e->e.e_phoff);
sewardjec7be9c2006-10-17 01:59:30 +0000170 if (sres.isError || sres.res != phsz) {
sewardj45f4e7c2005-09-27 19:20:21 +0000171 VG_(printf)("valgrind: can't read phdr: %s\n",
sewardjec7be9c2006-10-17 01:59:30 +0000172 VG_(strerror)(sres.err));
sewardj45f4e7c2005-09-27 19:20:21 +0000173 VG_(free)(e->p);
njn12f266f2005-06-28 19:20:46 +0000174 goto bad;
fitzhardinge7e343cd2003-12-16 02:14:00 +0000175 }
176
177 return e;
njn12f266f2005-06-28 19:20:46 +0000178
179 bad:
sewardj45f4e7c2005-09-27 19:20:21 +0000180 VG_(free)(e);
njn12f266f2005-06-28 19:20:46 +0000181 return NULL;
fitzhardinge7e343cd2003-12-16 02:14:00 +0000182}
183
fitzhardinge7e343cd2003-12-16 02:14:00 +0000184/* Map an ELF file. Returns the brk address. */
sewardj2c5ffbe2005-03-12 13:32:06 +0000185static
fitzhardingeb50068f2004-02-24 23:42:55 +0000186ESZ(Addr) mapelf(struct elfinfo *e, ESZ(Addr) base)
fitzhardinge7e343cd2003-12-16 02:14:00 +0000187{
sewardj45f4e7c2005-09-27 19:20:21 +0000188 Int i;
189 SysRes res;
fitzhardinge7e343cd2003-12-16 02:14:00 +0000190 ESZ(Addr) elfbrk = 0;
191
192 for(i = 0; i < e->e.e_phnum; i++) {
193 ESZ(Phdr) *ph = &e->p[i];
194 ESZ(Addr) addr, brkaddr;
195 ESZ(Word) memsz;
196
197 if (ph->p_type != PT_LOAD)
198 continue;
199
nethercote6c3cf412004-10-26 13:32:11 +0000200 addr = ph->p_vaddr+base;
201 memsz = ph->p_memsz;
fitzhardinge7e343cd2003-12-16 02:14:00 +0000202 brkaddr = addr+memsz;
203
204 if (brkaddr > elfbrk)
205 elfbrk = brkaddr;
206 }
207
fitzhardinge7e343cd2003-12-16 02:14:00 +0000208 for(i = 0; i < e->e.e_phnum; i++) {
209 ESZ(Phdr) *ph = &e->p[i];
210 ESZ(Addr) addr, bss, brkaddr;
211 ESZ(Off) off;
212 ESZ(Word) filesz;
213 ESZ(Word) memsz;
fitzhardinge7e343cd2003-12-16 02:14:00 +0000214 unsigned prot = 0;
215
216 if (ph->p_type != PT_LOAD)
217 continue;
218
sewardj45f4e7c2005-09-27 19:20:21 +0000219 if (ph->p_flags & PF_X) prot |= VKI_PROT_EXEC;
220 if (ph->p_flags & PF_W) prot |= VKI_PROT_WRITE;
221 if (ph->p_flags & PF_R) prot |= VKI_PROT_READ;
fitzhardinge7e343cd2003-12-16 02:14:00 +0000222
nethercote6c3cf412004-10-26 13:32:11 +0000223 addr = ph->p_vaddr+base;
224 off = ph->p_offset;
225 filesz = ph->p_filesz;
226 bss = addr+filesz;
227 memsz = ph->p_memsz;
fitzhardinge7e343cd2003-12-16 02:14:00 +0000228 brkaddr = addr+memsz;
229
njnf7fbe6c2004-11-30 11:40:24 +0000230 // Tom says: In the following, do what the Linux kernel does and only
231 // map the pages that are required instead of rounding everything to
232 // the specified alignment (ph->p_align). (AMD64 doesn't work if you
233 // use ph->p_align -- part of stage2's memory gets trashed somehow.)
njn098da062005-03-26 16:22:43 +0000234 //
235 // The condition handles the case of a zero-length segment.
njn13bfd852005-06-02 03:52:53 +0000236 if (VG_PGROUNDUP(bss)-VG_PGROUNDDN(addr) > 0) {
sewardj45f4e7c2005-09-27 19:20:21 +0000237 if (0) VG_(debugLog)(0,"ume","mmap_file_fixed_client #1\n");
238 res = VG_(am_mmap_file_fixed_client)(
239 VG_PGROUNDDN(addr),
240 VG_PGROUNDUP(bss)-VG_PGROUNDDN(addr),
241 prot, /*VKI_MAP_FIXED|VKI_MAP_PRIVATE, */
242 e->fd, VG_PGROUNDDN(off)
243 );
244 if (0) VG_(am_show_nsegments)(0,"after #1");
245 check_mmap(res, VG_PGROUNDDN(addr),
246 VG_PGROUNDUP(bss)-VG_PGROUNDDN(addr));
njn098da062005-03-26 16:22:43 +0000247 }
njnf7fbe6c2004-11-30 11:40:24 +0000248
249 // if memsz > filesz, fill the remainder with zeroed pages
fitzhardinge7e343cd2003-12-16 02:14:00 +0000250 if (memsz > filesz) {
251 UInt bytes;
252
njn13bfd852005-06-02 03:52:53 +0000253 bytes = VG_PGROUNDUP(brkaddr)-VG_PGROUNDUP(bss);
nethercotebfed1c82004-07-17 12:57:44 +0000254 if (bytes > 0) {
sewardj45f4e7c2005-09-27 19:20:21 +0000255 if (0) VG_(debugLog)(0,"ume","mmap_anon_fixed_client #2\n");
256 res = VG_(am_mmap_anon_fixed_client)(
257 VG_PGROUNDUP(bss), bytes,
258 prot
259 );
260 if (0) VG_(am_show_nsegments)(0,"after #2");
261 check_mmap(res, VG_PGROUNDUP(bss), bytes);
nethercotebfed1c82004-07-17 12:57:44 +0000262 }
fitzhardinge7e343cd2003-12-16 02:14:00 +0000263
nethercote73b526f2004-10-31 18:48:21 +0000264 bytes = bss & (VKI_PAGE_SIZE - 1);
njn098da062005-03-26 16:22:43 +0000265
266 // The 'prot' condition allows for a read-only bss
sewardj45f4e7c2005-09-27 19:20:21 +0000267 if ((prot & VKI_PROT_WRITE) && (bytes > 0)) {
nethercote73b526f2004-10-31 18:48:21 +0000268 bytes = VKI_PAGE_SIZE - bytes;
sewardj45f4e7c2005-09-27 19:20:21 +0000269 VG_(memset)((char *)bss, 0, bytes);
fitzhardinge7e343cd2003-12-16 02:14:00 +0000270 }
271 }
272 }
273
274 return elfbrk;
275}
276
njn73750612005-10-14 03:11:30 +0000277static Bool match_ELF(const char *hdr, Int len)
fitzhardinge7e343cd2003-12-16 02:14:00 +0000278{
279 ESZ(Ehdr) *e = (ESZ(Ehdr) *)hdr;
sewardj45f4e7c2005-09-27 19:20:21 +0000280 return (len > sizeof(*e)) && VG_(memcmp)(&e->e_ident[0], ELFMAG, SELFMAG) == 0;
fitzhardinge7e343cd2003-12-16 02:14:00 +0000281}
282
sewardj45f4e7c2005-09-27 19:20:21 +0000283
284/* load_ELF pulls an ELF executable into the address space, prepares
285 it for execution, and writes info about it into INFO. In
286 particular it fills in .init_eip, which is the starting point.
287
288 Returns zero on success, non-zero (a VKI_E.. value) on failure.
289
290 The sequence of activities is roughly as follows:
291
292 - use readelf() to extract program header info from the exe file.
293
294 - scan the program header, collecting info (not sure what all those
295 info-> fields are, or whether they are used, but still) and in
296 particular looking out fo the PT_INTERP header, which describes
297 the interpreter. If such a field is found, the space needed to
298 hold the interpreter is computed into interp_size.
299
300 - map the executable in, by calling mapelf(). This maps in all
301 loadable sections, and I _think_ also creates any .bss areas
302 required. mapelf() returns the address just beyond the end of
303 the furthest-along mapping it creates. The executable is mapped
304 starting at EBASE, which is usually read from it (eg, 0x8048000
305 etc) except if it's a PIE, in which case I'm not sure what
306 happens.
307
308 The returned address is recorded in info->brkbase as the start
309 point of the brk (data) segment, as it is traditional to place
310 the data segment just after the executable. Neither load_ELF nor
311 mapelf creates the brk segment, though: that is for the caller of
312 load_ELF to attend to.
313
314 - If the initial phdr scan didn't find any mention of an
315 interpreter (interp == NULL), this must be a statically linked
316 executable, and we're pretty much done.
317
318 - Otherwise, we need to use mapelf() a second time to load the
319 interpreter. The interpreter can go anywhere, but mapelf() wants
320 to be told a specific address to put it at. So an advisory query
321 is passed to aspacem, asking where it would put an anonymous
322 client mapping of size INTERP_SIZE. That address is then used
323 as the mapping address for the interpreter.
324
325 - The entry point in INFO is set to the interpreter's entry point,
326 and we're done. */
sewardj13247ca2005-12-30 22:52:20 +0000327static Int load_ELF(Int fd, const HChar* name, /*MOD*/ExeInfo* info)
fitzhardinge7e343cd2003-12-16 02:14:00 +0000328{
sewardj45f4e7c2005-09-27 19:20:21 +0000329 SysRes sres;
fitzhardinge7e343cd2003-12-16 02:14:00 +0000330 struct elfinfo *e;
331 struct elfinfo *interp = NULL;
fitzhardingeca9bd9c2004-09-08 20:05:02 +0000332 ESZ(Addr) minaddr = ~0; /* lowest mapped address */
333 ESZ(Addr) maxaddr = 0; /* highest mapped address */
334 ESZ(Addr) interp_addr = 0; /* interpreter (ld.so) address */
335 ESZ(Word) interp_size = 0; /* interpreter size */
nethercote73b526f2004-10-31 18:48:21 +0000336 ESZ(Word) interp_align = VKI_PAGE_SIZE;
njn73750612005-10-14 03:11:30 +0000337 Int i;
fitzhardinge7e343cd2003-12-16 02:14:00 +0000338 void *entry;
nethercote7f390022004-10-25 17:18:24 +0000339 ESZ(Addr) ebase = 0;
340
sewardj2f22bd72006-01-20 21:45:36 +0000341 /* The difference between where the interpreter got mapped and
342 where it asked to be mapped. Needed for computing the ppc64 ELF
343 entry point and initial tocptr (R2) value. */
344 ESZ(Word) interp_offset = 0;
345
nethercote7f390022004-10-25 17:18:24 +0000346#ifdef HAVE_PIE
347 ebase = info->exe_base;
348#endif
fitzhardinge7e343cd2003-12-16 02:14:00 +0000349
350 e = readelf(fd, name);
351
352 if (e == NULL)
sewardj45f4e7c2005-09-27 19:20:21 +0000353 return VKI_ENOEXEC;
fitzhardinge7e343cd2003-12-16 02:14:00 +0000354
tomd6dd9912005-07-18 15:52:30 +0000355 /* The kernel maps position-independent executables at TASK_SIZE*2/3;
356 duplicate this behavior as close as we can. */
357 if (e->e.e_type == ET_DYN && ebase == 0) {
sewardj9c606bd2008-09-18 18:12:50 +0000358 ebase = VG_PGROUNDDN(info->exe_base
359 + (info->exe_end - info->exe_base) * 2 / 3);
360 /* We really don't want to load PIEs at zero or too close. It
361 works, but it's unrobust (NULL pointer reads and writes
362 become legit, which is really bad) and causes problems for
363 exp-ptrcheck, which assumes all numbers below 1MB are
364 nonpointers. So, hackily, move it above 1MB. */
365 if (ebase < 0x100000)
366 ebase = 0x100000;
tomd6dd9912005-07-18 15:52:30 +0000367 }
368
fitzhardinge7e343cd2003-12-16 02:14:00 +0000369 info->phnum = e->e.e_phnum;
nethercote7f390022004-10-25 17:18:24 +0000370 info->entry = e->e.e_entry + ebase;
sewardjb5f6f512005-03-10 23:59:00 +0000371 info->phdr = 0;
fitzhardinge7e343cd2003-12-16 02:14:00 +0000372
373 for(i = 0; i < e->e.e_phnum; i++) {
374 ESZ(Phdr) *ph = &e->p[i];
375
376 switch(ph->p_type) {
377 case PT_PHDR:
nethercote7f390022004-10-25 17:18:24 +0000378 info->phdr = ph->p_vaddr + ebase;
fitzhardinge7e343cd2003-12-16 02:14:00 +0000379 break;
380
381 case PT_LOAD:
382 if (ph->p_vaddr < minaddr)
383 minaddr = ph->p_vaddr;
384 if (ph->p_vaddr+ph->p_memsz > maxaddr)
385 maxaddr = ph->p_vaddr+ph->p_memsz;
386 break;
387
388 case PT_INTERP: {
sewardj9c606bd2008-09-18 18:12:50 +0000389 HChar *buf = VG_(malloc)("ume.LE.1", ph->p_filesz+1);
njn73750612005-10-14 03:11:30 +0000390 Int j;
391 Int intfd;
392 Int baseaddr_set;
fitzhardinge7e343cd2003-12-16 02:14:00 +0000393
sewardj45f4e7c2005-09-27 19:20:21 +0000394 vg_assert(buf);
395 VG_(pread)(fd, buf, ph->p_filesz, ph->p_offset);
fitzhardinge7e343cd2003-12-16 02:14:00 +0000396 buf[ph->p_filesz] = '\0';
397
sewardj45f4e7c2005-09-27 19:20:21 +0000398 sres = VG_(open)(buf, VKI_O_RDONLY, 0);
399 if (sres.isError) {
400 VG_(printf)("valgrind: m_ume.c: can't open interpreter\n");
401 VG_(exit)(1);
fitzhardinge7e343cd2003-12-16 02:14:00 +0000402 }
sewardjec7be9c2006-10-17 01:59:30 +0000403 intfd = sres.res;
fitzhardinge7e343cd2003-12-16 02:14:00 +0000404
405 interp = readelf(intfd, buf);
406 if (interp == NULL) {
sewardj45f4e7c2005-09-27 19:20:21 +0000407 VG_(printf)("valgrind: m_ume.c: can't read interpreter\n");
fitzhardinge7e343cd2003-12-16 02:14:00 +0000408 return 1;
409 }
sewardj45f4e7c2005-09-27 19:20:21 +0000410 VG_(free)(buf);
fitzhardinge7e343cd2003-12-16 02:14:00 +0000411
412 baseaddr_set = 0;
413 for(j = 0; j < interp->e.e_phnum; j++) {
414 ESZ(Phdr) *iph = &interp->p[j];
415 ESZ(Addr) end;
416
417 if (iph->p_type != PT_LOAD)
418 continue;
419
420 if (!baseaddr_set) {
nethercote7f390022004-10-25 17:18:24 +0000421 interp_addr = iph->p_vaddr;
422 interp_align = iph->p_align;
fitzhardinge7e343cd2003-12-16 02:14:00 +0000423 baseaddr_set = 1;
424 }
425
426 /* assumes that all segments in the interp are close */
427 end = (iph->p_vaddr - interp_addr) + iph->p_memsz;
428
429 if (end > interp_size)
430 interp_size = end;
431 }
432 break;
nethercoteb24cbc82004-09-03 23:25:33 +0000433
434 default:
435 // do nothing
436 break;
fitzhardinge7e343cd2003-12-16 02:14:00 +0000437 }
438 }
439 }
440
sewardjb5f6f512005-03-10 23:59:00 +0000441 if (info->phdr == 0)
tomd6dd9912005-07-18 15:52:30 +0000442 info->phdr = minaddr + ebase + e->e.e_phoff;
sewardjb5f6f512005-03-10 23:59:00 +0000443
fitzhardinge7e343cd2003-12-16 02:14:00 +0000444 if (info->exe_base != info->exe_end) {
445 if (minaddr >= maxaddr ||
nethercote7f390022004-10-25 17:18:24 +0000446 (minaddr + ebase < info->exe_base ||
447 maxaddr + ebase > info->exe_end)) {
sewardj45f4e7c2005-09-27 19:20:21 +0000448 VG_(printf)("Executable range %p-%p is outside the\n"
449 "acceptable range %p-%p\n",
tom151a6392005-11-11 12:30:36 +0000450 (char *)minaddr + ebase, (char *)maxaddr + ebase,
451 (char *)info->exe_base, (char *)info->exe_end);
sewardj45f4e7c2005-09-27 19:20:21 +0000452 return VKI_ENOMEM;
fitzhardinge7e343cd2003-12-16 02:14:00 +0000453 }
454 }
455
nethercote7f390022004-10-25 17:18:24 +0000456 info->brkbase = mapelf(e, ebase); /* map the executable */
fitzhardinge7e343cd2003-12-16 02:14:00 +0000457
fitzhardinge92360792003-12-24 10:11:11 +0000458 if (info->brkbase == 0)
sewardj45f4e7c2005-09-27 19:20:21 +0000459 return VKI_ENOMEM;
fitzhardinge92360792003-12-24 10:11:11 +0000460
fitzhardinge7e343cd2003-12-16 02:14:00 +0000461 if (interp != NULL) {
462 /* reserve a chunk of address space for interpreter */
tom069e6412005-11-01 19:46:07 +0000463 MapRequest mreq;
sewardj45f4e7c2005-09-27 19:20:21 +0000464 Addr advised;
465 Bool ok;
fitzhardinge7e343cd2003-12-16 02:14:00 +0000466
sewardj45f4e7c2005-09-27 19:20:21 +0000467 /* Don't actually reserve the space. Just get an advisory
468 indicating where it would be allocated, and pass that to
469 mapelf(), which in turn asks aspacem to do some fixed maps at
470 the specified address. This is a bit of hack, but it should
471 work because there should be no intervening transactions with
sewardj09f61732005-11-02 19:41:21 +0000472 aspacem which could cause those fixed maps to fail.
473
474 Placement policy is:
475
476 if the interpreter asks to be loaded at zero
477 ignore that and put it wherever we like (mappings at zero
478 are bad news)
479 else
480 try and put it where it asks for, but if that doesn't work,
481 just put it anywhere.
482 */
483 if (interp_addr == 0) {
484 mreq.rkind = MAny;
485 mreq.start = 0;
486 mreq.len = interp_size;
487 } else {
488 mreq.rkind = MHint;
489 mreq.start = interp_addr;
490 mreq.len = interp_size;
491 }
492
tom069e6412005-11-01 19:46:07 +0000493 advised = VG_(am_get_advisory)( &mreq, True/*client*/, &ok );
sewardj09f61732005-11-02 19:41:21 +0000494
sewardj45f4e7c2005-09-27 19:20:21 +0000495 if (!ok) {
496 /* bomb out */
497 SysRes res = VG_(mk_SysRes_Error)(VKI_EINVAL);
498 if (0) VG_(printf)("reserve for interp: failed\n");
499 check_mmap(res, (Addr)interp_addr, interp_size);
500 /*NOTREACHED*/
fitzhardinge7e343cd2003-12-16 02:14:00 +0000501 }
502
sewardj45f4e7c2005-09-27 19:20:21 +0000503 (void)mapelf(interp, (ESZ(Addr))advised - interp_addr);
fitzhardinge7e343cd2003-12-16 02:14:00 +0000504
sewardj45f4e7c2005-09-27 19:20:21 +0000505 VG_(close)(interp->fd);
fitzhardinge7e343cd2003-12-16 02:14:00 +0000506
sewardj45f4e7c2005-09-27 19:20:21 +0000507 entry = (void *)(advised - interp_addr + interp->e.e_entry);
508 info->interp_base = (ESZ(Addr))advised;
sewardj2f22bd72006-01-20 21:45:36 +0000509 interp_offset = advised - interp_addr;
fitzhardinge7e343cd2003-12-16 02:14:00 +0000510
sewardj45f4e7c2005-09-27 19:20:21 +0000511 VG_(free)(interp->p);
512 VG_(free)(interp);
fitzhardinge7e343cd2003-12-16 02:14:00 +0000513 } else
tomd6dd9912005-07-18 15:52:30 +0000514 entry = (void *)(ebase + e->e.e_entry);
fitzhardinge7e343cd2003-12-16 02:14:00 +0000515
nethercote7f390022004-10-25 17:18:24 +0000516 info->exe_base = minaddr + ebase;
517 info->exe_end = maxaddr + ebase;
fitzhardinge7e343cd2003-12-16 02:14:00 +0000518
sewardjbd8951e2005-12-06 21:47:38 +0000519#if defined(VGP_ppc64_linux)
520 /* On PPC64, a func ptr is represented by a TOC entry ptr. This
521 TOC entry contains three words; the first word is the function
522 address, the second word is the TOC ptr (r2), and the third word
523 is the static chain value. */
sewardj13247ca2005-12-30 22:52:20 +0000524 info->init_ip = ((ULong*)entry)[0];
525 info->init_toc = ((ULong*)entry)[1];
sewardj2f22bd72006-01-20 21:45:36 +0000526 info->init_ip += interp_offset;
527 info->init_toc += interp_offset;
sewardjbd8951e2005-12-06 21:47:38 +0000528#else
sewardj13247ca2005-12-30 22:52:20 +0000529 info->init_ip = (Addr)entry;
530 info->init_toc = 0; /* meaningless on this platform */
sewardjbd8951e2005-12-06 21:47:38 +0000531#endif
sewardj45f4e7c2005-09-27 19:20:21 +0000532 VG_(free)(e->p);
533 VG_(free)(e);
fitzhardinge7e343cd2003-12-16 02:14:00 +0000534
535 return 0;
536}
537
538
njn73750612005-10-14 03:11:30 +0000539static Bool match_script(char *hdr, Int len)
fitzhardinge7e343cd2003-12-16 02:14:00 +0000540{
njn73750612005-10-14 03:11:30 +0000541 Char* end = hdr + len;
542 Char* interp = hdr + 2;
543
544 // len < 4: need '#', '!', plus at least a '/' and one more char
545 if (len < 4) return False;
546 if (0 != VG_(memcmp)(hdr, "#!", 2)) return False;
547
548 // Find interpreter name, make sure it's an absolute path (starts with
sewardjf94bf6c2006-07-05 22:54:49 +0000549 // '/') and has at least one more char. First, skip over any space
550 // between the #! and the start of the interpreter name
njn73750612005-10-14 03:11:30 +0000551 while (interp < end && VG_(isspace)(*interp)) interp++;
sewardjf94bf6c2006-07-05 22:54:49 +0000552
553 // overrun?
554 if (interp >= end) return False; // can't find start of interp name
555
556 // interp should now point at the /
njn73750612005-10-14 03:11:30 +0000557 if (*interp != '/') return False; // absolute path only for interpreter
sewardjf94bf6c2006-07-05 22:54:49 +0000558
559 // check for something plausible after the /
560 interp++;
561 if (interp >= end) return False;
562 if (VG_(isspace)(*interp)) return False;
njn73750612005-10-14 03:11:30 +0000563
564 // Here we should get the full interpreter name and check it with
565 // check_executable(). See the "EXEC FAILED" failure when running shell
566 // for an example.
567
568 return True; // looks like a #! script
fitzhardinge7e343cd2003-12-16 02:14:00 +0000569}
570
njn73750612005-10-14 03:11:30 +0000571// Forward declaration.
sewardj13247ca2005-12-30 22:52:20 +0000572static Int do_exec_inner(const HChar* exe, ExeInfo* info);
fitzhardinge7e343cd2003-12-16 02:14:00 +0000573
njn73750612005-10-14 03:11:30 +0000574/* returns: 0 = success, non-0 is failure */
sewardj13247ca2005-12-30 22:52:20 +0000575static Int load_script(Int fd, const HChar* name, ExeInfo* info)
njn73750612005-10-14 03:11:30 +0000576{
sewardje428ab02007-05-05 11:40:35 +0000577 Char hdr[4096];
578 Int len = 4096;
njn73750612005-10-14 03:11:30 +0000579 Int eol;
580 Char* interp;
581 Char* end;
582 Char* cp;
583 Char* arg = NULL;
584 SysRes res;
585
586 // Read the first part of the file.
587 res = VG_(pread)(fd, hdr, len, 0);
588 if (res.isError) {
589 VG_(close)(fd);
590 return VKI_EACCES;
591 } else {
sewardjec7be9c2006-10-17 01:59:30 +0000592 len = res.res;
njn73750612005-10-14 03:11:30 +0000593 }
594
595 vg_assert('#' == hdr[0] && '!' == hdr[1]);
596
597 end = hdr + len;
fitzhardinge7e343cd2003-12-16 02:14:00 +0000598 interp = hdr + 2;
njn73750612005-10-14 03:11:30 +0000599 while (interp < end && VG_(isspace)(*interp))
fitzhardinge7e343cd2003-12-16 02:14:00 +0000600 interp++;
601
njn73750612005-10-14 03:11:30 +0000602 vg_assert(*interp == '/'); /* absolute path only for interpreter */
fitzhardinge7e343cd2003-12-16 02:14:00 +0000603
604 /* skip over interpreter name */
njn73750612005-10-14 03:11:30 +0000605 for (cp = interp; cp < end && !VG_(isspace)(*cp); cp++)
fitzhardinge7e343cd2003-12-16 02:14:00 +0000606 ;
607
608 eol = (*cp == '\n');
609
610 *cp++ = '\0';
611
612 if (!eol && cp < end) {
613 /* skip space before arg */
sewardjf94bf6c2006-07-05 22:54:49 +0000614 while (cp < end && VG_(isspace)(*cp) && *cp != '\n')
fitzhardinge7e343cd2003-12-16 02:14:00 +0000615 cp++;
616
617 /* arg is from here to eol */
618 arg = cp;
619 while (cp < end && *cp != '\n')
620 cp++;
621 *cp = '\0';
622 }
623
sewardj9c606bd2008-09-18 18:12:50 +0000624 info->interp_name = VG_(strdup)("ume.ls.1", interp);
sewardj45f4e7c2005-09-27 19:20:21 +0000625 vg_assert(NULL != info->interp_name);
nethercote71980f02004-01-24 18:18:54 +0000626 if (arg != NULL && *arg != '\0') {
sewardj9c606bd2008-09-18 18:12:50 +0000627 info->interp_args = VG_(strdup)("ume.ls.2", arg);
sewardj45f4e7c2005-09-27 19:20:21 +0000628 vg_assert(NULL != info->interp_args);
nethercote71980f02004-01-24 18:18:54 +0000629 }
fitzhardinge7e343cd2003-12-16 02:14:00 +0000630
631 if (info->argv && info->argv[0] != NULL)
632 info->argv[0] = (char *)name;
633
634 if (0)
sewardj45f4e7c2005-09-27 19:20:21 +0000635 VG_(printf)("#! script: interp_name=\"%s\" interp_args=\"%s\"\n",
636 info->interp_name, info->interp_args);
fitzhardinge7e343cd2003-12-16 02:14:00 +0000637
638 return do_exec_inner(interp, info);
639}
640
fitzhardingefd7da3a2004-09-08 20:05:29 +0000641
njn73750612005-10-14 03:11:30 +0000642typedef enum {
643 VG_EXE_FORMAT_ELF = 1,
644 VG_EXE_FORMAT_SCRIPT = 2,
645} ExeFormat;
fitzhardingefd7da3a2004-09-08 20:05:29 +0000646
njn73750612005-10-14 03:11:30 +0000647// Check the file looks executable.
sewardjc74b3ba2007-11-17 21:11:57 +0000648SysRes
649VG_(pre_exec_check)(const HChar* exe_name, Int* out_fd, Bool allow_setuid)
fitzhardingefd7da3a2004-09-08 20:05:29 +0000650{
njn73750612005-10-14 03:11:30 +0000651 Int fd, ret;
652 SysRes res;
sewardje428ab02007-05-05 11:40:35 +0000653 Char buf[4096];
654 SizeT bufsz = 4096, fsz;
sewardjc74b3ba2007-11-17 21:11:57 +0000655 Bool is_setuid = False;
fitzhardingefd7da3a2004-09-08 20:05:29 +0000656
njn73750612005-10-14 03:11:30 +0000657 // Check it's readable
658 res = VG_(open)(exe_name, VKI_O_RDONLY, 0);
659 if (res.isError) {
660 return res;
661 }
sewardjec7be9c2006-10-17 01:59:30 +0000662 fd = res.res;
fitzhardingefd7da3a2004-09-08 20:05:29 +0000663
njn73750612005-10-14 03:11:30 +0000664 // Check we have execute permissions
sewardjc74b3ba2007-11-17 21:11:57 +0000665 ret = VG_(check_executable)(&is_setuid, (HChar*)exe_name, allow_setuid);
njn73750612005-10-14 03:11:30 +0000666 if (0 != ret) {
667 VG_(close)(fd);
sewardjc74b3ba2007-11-17 21:11:57 +0000668 if (is_setuid && !VG_(clo_xml)) {
669 VG_(message)(Vg_UserMsg, "");
670 VG_(message)(Vg_UserMsg,
671 "Warning: Can't execute setuid/setgid executable: %s",
672 exe_name);
673 VG_(message)(Vg_UserMsg, "Possible workaround: remove "
674 "--trace-children=yes, if in effect");
675 VG_(message)(Vg_UserMsg, "");
676 }
njn73750612005-10-14 03:11:30 +0000677 return VG_(mk_SysRes_Error)(ret);
fitzhardingefd7da3a2004-09-08 20:05:29 +0000678 }
679
sewardjec61b652008-08-19 07:03:04 +0000680 fsz = (SizeT)VG_(fsize)(fd);
njn73750612005-10-14 03:11:30 +0000681 if (fsz < bufsz)
682 bufsz = fsz;
683
684 res = VG_(pread)(fd, buf, bufsz, 0);
sewardjec7be9c2006-10-17 01:59:30 +0000685 if (res.isError || res.res != bufsz) {
njn73750612005-10-14 03:11:30 +0000686 VG_(close)(fd);
687 return VG_(mk_SysRes_Error)(VKI_EACCES);
688 }
sewardjec7be9c2006-10-17 01:59:30 +0000689 bufsz = res.res;
njn73750612005-10-14 03:11:30 +0000690
691 if (match_ELF(buf, bufsz)) {
692 res = VG_(mk_SysRes_Success)(VG_EXE_FORMAT_ELF);
693 } else if (match_script(buf, bufsz)) {
694 res = VG_(mk_SysRes_Success)(VG_EXE_FORMAT_SCRIPT);
fitzhardingefd7da3a2004-09-08 20:05:29 +0000695 } else {
njn73750612005-10-14 03:11:30 +0000696 res = VG_(mk_SysRes_Error)(VKI_ENOEXEC);
fitzhardingefd7da3a2004-09-08 20:05:29 +0000697 }
698
njn73750612005-10-14 03:11:30 +0000699 // Write the 'out_fd' param if necessary, or close the file.
700 if (!res.isError && out_fd) {
701 *out_fd = fd;
702 } else {
703 VG_(close)(fd);
704 }
705
706 return res;
fitzhardingefd7da3a2004-09-08 20:05:29 +0000707}
708
njn73750612005-10-14 03:11:30 +0000709// returns: 0 = success, non-0 is failure
710//
711// We can execute only ELF binaries or scripts that begin with "#!". (Not,
712// for example, scripts that don't begin with "#!"; see the VG_(do_exec)()
713// invocation from m_main.c for how that's handled.)
sewardj13247ca2005-12-30 22:52:20 +0000714static Int do_exec_inner(const HChar *exe, ExeInfo* info)
fitzhardinge7e343cd2003-12-16 02:14:00 +0000715{
njn73750612005-10-14 03:11:30 +0000716 SysRes res;
717 Int fd;
718 Int ret;
fitzhardinge7e343cd2003-12-16 02:14:00 +0000719
sewardjc74b3ba2007-11-17 21:11:57 +0000720 res = VG_(pre_exec_check)(exe, &fd, False/*allow_setuid*/);
njn73750612005-10-14 03:11:30 +0000721 if (res.isError)
sewardjec7be9c2006-10-17 01:59:30 +0000722 return res.err;
fitzhardinge7e343cd2003-12-16 02:14:00 +0000723
sewardjec7be9c2006-10-17 01:59:30 +0000724 switch (res.res) {
njn73750612005-10-14 03:11:30 +0000725 case VG_EXE_FORMAT_ELF: ret = load_ELF (fd, exe, info); break;
726 case VG_EXE_FORMAT_SCRIPT: ret = load_script(fd, exe, info); break;
727 default:
728 vg_assert2(0, "unrecognised VG_EXE_FORMAT value\n");
fitzhardinge7e343cd2003-12-16 02:14:00 +0000729 }
730
sewardj45f4e7c2005-09-27 19:20:21 +0000731 VG_(close)(fd);
fitzhardinge7e343cd2003-12-16 02:14:00 +0000732
733 return ret;
734}
735
njn73750612005-10-14 03:11:30 +0000736
737static Bool is_hash_bang_file(Char* f)
738{
739 SysRes res = VG_(open)(f, VKI_O_RDONLY, 0);
740 if (!res.isError) {
741 Char buf[3] = {0,0,0};
sewardjec7be9c2006-10-17 01:59:30 +0000742 Int fd = res.res;
njn73750612005-10-14 03:11:30 +0000743 Int n = VG_(read)(fd, buf, 2);
744 if (n == 2 && VG_STREQ("#!", buf))
745 return True;
746 }
747 return False;
748}
749
750// Look at the first 80 chars, and if any are greater than 127, it's binary.
751// This is crude, but should be good enough. Note that it fails on a
752// zero-length file, as we want.
753static Bool is_binary_file(Char* f)
754{
755 SysRes res = VG_(open)(f, VKI_O_RDONLY, 0);
756 if (!res.isError) {
757 UChar buf[80];
sewardjec7be9c2006-10-17 01:59:30 +0000758 Int fd = res.res;
njn73750612005-10-14 03:11:30 +0000759 Int n = VG_(read)(fd, buf, 80);
760 Int i;
761 for (i = 0; i < n; i++) {
762 if (buf[i] > 127)
763 return True; // binary char found
764 }
765 return False;
766 } else {
767 // Something went wrong. This will only happen if we earlier
768 // succeeded in opening the file but fail here (eg. the file was
769 // deleted between then and now).
770 VG_(printf)("valgrind: %s: unknown error\n", f);
771 VG_(exit)(126); // 126 == NOEXEC
772 }
773}
774
775// If the do_exec fails we try to emulate what the shell does (I used
776// bash as a guide). It's worth noting that the shell can execute some
777// things that VG_(do_exec)() (which subsitutes for the kernel's exec())
778// will refuse to (eg. scripts lacking a "#!" prefix).
sewardj13247ca2005-12-30 22:52:20 +0000779static Int do_exec_shell_followup(Int ret, HChar* exe_name,
780 ExeInfo* info)
njn73750612005-10-14 03:11:30 +0000781{
782 Char* default_interp_name = "/bin/sh";
783 SysRes res;
sewardjec61b652008-08-19 07:03:04 +0000784 struct vg_stat st;
njn73750612005-10-14 03:11:30 +0000785
786 if (VKI_ENOEXEC == ret) {
787 // It was an executable file, but in an unacceptable format. Probably
788 // is a shell script lacking the "#!" prefix; try to execute it so.
789
790 // Is it a binary file?
791 if (is_binary_file(exe_name)) {
792 VG_(printf)("valgrind: %s: cannot execute binary file\n", exe_name);
793 VG_(exit)(126); // 126 == NOEXEC
794 }
795
796 // Looks like a script. Run it with /bin/sh. This includes
797 // zero-length files.
798
sewardj9c606bd2008-09-18 18:12:50 +0000799 info->interp_name = VG_(strdup)("ume.desf.1", default_interp_name);
njn73750612005-10-14 03:11:30 +0000800 info->interp_args = NULL;
801 if (info->argv && info->argv[0] != NULL)
802 info->argv[0] = (char *)exe_name;
803
804 ret = do_exec_inner(info->interp_name, info);
805
806 if (0 != ret) {
807 // Something went wrong with executing the default interpreter
808 VG_(printf)("valgrind: %s: bad interpreter (%s): %s\n",
809 exe_name, info->interp_name, VG_(strerror)(ret));
810 VG_(exit)(126); // 126 == NOEXEC
811 }
812
813 } else if (0 != ret) {
814 // Something else went wrong. Try to make the error more specific,
815 // and then print a message and abort.
816
817 // Was it a directory?
818 res = VG_(stat)(exe_name, &st);
819 if (!res.isError && VKI_S_ISDIR(st.st_mode)) {
820 VG_(printf)("valgrind: %s: is a directory\n", exe_name);
821
822 // Was it not executable?
sewardjc74b3ba2007-11-17 21:11:57 +0000823 } else if (0 != VG_(check_executable)(NULL, exe_name,
824 False/*allow_setuid*/)) {
njn73750612005-10-14 03:11:30 +0000825 VG_(printf)("valgrind: %s: %s\n", exe_name, VG_(strerror)(ret));
826
827 // Did it start with "#!"? If so, it must have been a bad interpreter.
828 } else if (is_hash_bang_file(exe_name)) {
829 VG_(printf)("valgrind: %s: bad interpreter: %s\n",
830 exe_name, VG_(strerror)(ret));
831
832 // Otherwise it was something else.
833 } else {
tom3108a9b2006-05-24 10:00:53 +0000834 VG_(printf)("valgrind: %s: %s\n", exe_name, VG_(strerror)(ret));
njn73750612005-10-14 03:11:30 +0000835 }
836 // 126 means NOEXEC; I think this is Posix, and that in some cases we
837 // should be returning 127, meaning NOTFOUND. Oh well.
838 VG_(exit)(126);
839 }
840 return ret;
841}
842
843
844// This emulates the kernel's exec(). If it fails, it then emulates the
845// shell's handling of the situation.
nethercoteea147e72004-07-26 15:43:57 +0000846// See ume.h for an indication of which entries of 'info' are inputs, which
847// are outputs, and which are both.
sewardj45f4e7c2005-09-27 19:20:21 +0000848/* returns: 0 = success, non-0 is failure */
sewardj13247ca2005-12-30 22:52:20 +0000849Int VG_(do_exec)(const HChar* exe_name, ExeInfo* info)
fitzhardinge7e343cd2003-12-16 02:14:00 +0000850{
njn73750612005-10-14 03:11:30 +0000851 Int ret;
852
nethercoted6a56872004-07-26 15:32:47 +0000853 info->interp_name = NULL;
854 info->interp_args = NULL;
fitzhardinge7e343cd2003-12-16 02:14:00 +0000855
njn73750612005-10-14 03:11:30 +0000856 ret = do_exec_inner(exe_name, info);
857
858 if (0 != ret) {
sewardj1ac9d0c2007-05-01 14:18:48 +0000859 Char* exe_name_casted = (Char*)exe_name;
860 ret = do_exec_shell_followup(ret, exe_name_casted, info);
njn73750612005-10-14 03:11:30 +0000861 }
862 return ret;
fitzhardinge7e343cd2003-12-16 02:14:00 +0000863}
nethercotebb1c9912004-01-04 16:43:23 +0000864
sewardjec7be9c2006-10-17 01:59:30 +0000865#endif /* defined(VGO_linux) */
866
nethercotebb1c9912004-01-04 16:43:23 +0000867/*--------------------------------------------------------------------*/
njn08a2e172005-06-21 22:47:54 +0000868/*--- end ---*/
nethercotebb1c9912004-01-04 16:43:23 +0000869/*--------------------------------------------------------------------*/