macho.c revision f0c855fac3f394b3fad9c0d15d86381b4073e164
1f76d27a697a7b0bf3b84490baf60623fc96a23afnjn
2f76d27a697a7b0bf3b84490baf60623fc96a23afnjn/*--------------------------------------------------------------------*/
3f76d27a697a7b0bf3b84490baf60623fc96a23afnjn/*--- User-mode execve() for Mach-O executables      m_ume_macho.c ---*/
4f76d27a697a7b0bf3b84490baf60623fc96a23afnjn/*--------------------------------------------------------------------*/
5f76d27a697a7b0bf3b84490baf60623fc96a23afnjn
6f76d27a697a7b0bf3b84490baf60623fc96a23afnjn/*
7f76d27a697a7b0bf3b84490baf60623fc96a23afnjn   This file is part of Valgrind, a dynamic binary instrumentation
8f76d27a697a7b0bf3b84490baf60623fc96a23afnjn   framework.
9f76d27a697a7b0bf3b84490baf60623fc96a23afnjn
100f157ddb404bcde7815a1c5bf2d7e41c114f3d73sewardj   Copyright (C) 2005-2013 Apple Inc.
11f76d27a697a7b0bf3b84490baf60623fc96a23afnjn      Greg Parker  gparker@apple.com
12f76d27a697a7b0bf3b84490baf60623fc96a23afnjn
13f76d27a697a7b0bf3b84490baf60623fc96a23afnjn   This program is free software; you can redistribute it and/or
14f76d27a697a7b0bf3b84490baf60623fc96a23afnjn   modify it under the terms of the GNU General Public License as
15f76d27a697a7b0bf3b84490baf60623fc96a23afnjn   published by the Free Software Foundation; either version 2 of the
16f76d27a697a7b0bf3b84490baf60623fc96a23afnjn   License, or (at your option) any later version.
17f76d27a697a7b0bf3b84490baf60623fc96a23afnjn
18f76d27a697a7b0bf3b84490baf60623fc96a23afnjn   This program is distributed in the hope that it will be useful, but
19f76d27a697a7b0bf3b84490baf60623fc96a23afnjn   WITHOUT ANY WARRANTY; without even the implied warranty of
20f76d27a697a7b0bf3b84490baf60623fc96a23afnjn   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
21f76d27a697a7b0bf3b84490baf60623fc96a23afnjn   General Public License for more details.
22f76d27a697a7b0bf3b84490baf60623fc96a23afnjn
23f76d27a697a7b0bf3b84490baf60623fc96a23afnjn   You should have received a copy of the GNU General Public License
24f76d27a697a7b0bf3b84490baf60623fc96a23afnjn   along with this program; if not, write to the Free Software
25f76d27a697a7b0bf3b84490baf60623fc96a23afnjn   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
26f76d27a697a7b0bf3b84490baf60623fc96a23afnjn   02111-1307, USA.
27f76d27a697a7b0bf3b84490baf60623fc96a23afnjn
28f76d27a697a7b0bf3b84490baf60623fc96a23afnjn   The GNU General Public License is contained in the file COPYING.
29f76d27a697a7b0bf3b84490baf60623fc96a23afnjn*/
30f76d27a697a7b0bf3b84490baf60623fc96a23afnjn
318b68b64759254d514d98328c496cbd88cde4c9a5njn#if defined(VGO_darwin)
328b68b64759254d514d98328c496cbd88cde4c9a5njn
33f76d27a697a7b0bf3b84490baf60623fc96a23afnjn#include "pub_core_basics.h"
34f76d27a697a7b0bf3b84490baf60623fc96a23afnjn#include "pub_core_vki.h"
35f76d27a697a7b0bf3b84490baf60623fc96a23afnjn
36f76d27a697a7b0bf3b84490baf60623fc96a23afnjn#include "pub_core_aspacemgr.h"     // various mapping fns
37f76d27a697a7b0bf3b84490baf60623fc96a23afnjn#include "pub_core_debuglog.h"
38f76d27a697a7b0bf3b84490baf60623fc96a23afnjn#include "pub_core_libcassert.h"    // VG_(exit), vg_assert
39f76d27a697a7b0bf3b84490baf60623fc96a23afnjn#include "pub_core_libcbase.h"      // VG_(memcmp), etc
40f76d27a697a7b0bf3b84490baf60623fc96a23afnjn#include "pub_core_libcfile.h"      // VG_(open) et al
41f76d27a697a7b0bf3b84490baf60623fc96a23afnjn#include "pub_core_libcprint.h"
42f76d27a697a7b0bf3b84490baf60623fc96a23afnjn#include "pub_core_libcproc.h"
43f76d27a697a7b0bf3b84490baf60623fc96a23afnjn#include "pub_core_machine.h"       // VG_ELF_CLASS (XXX: which should be moved)
44f76d27a697a7b0bf3b84490baf60623fc96a23afnjn#include "pub_core_mallocfree.h"    // VG_(malloc), VG_(free)
45f76d27a697a7b0bf3b84490baf60623fc96a23afnjn#include "pub_core_syscall.h"       // VG_(strerror)
46f76d27a697a7b0bf3b84490baf60623fc96a23afnjn#include "pub_core_ume.h"           // self
47f76d27a697a7b0bf3b84490baf60623fc96a23afnjn
48f76d27a697a7b0bf3b84490baf60623fc96a23afnjn#include "priv_ume.h"
49f76d27a697a7b0bf3b84490baf60623fc96a23afnjn
50f76d27a697a7b0bf3b84490baf60623fc96a23afnjn#include <mach/mach.h>
51f76d27a697a7b0bf3b84490baf60623fc96a23afnjn
52f76d27a697a7b0bf3b84490baf60623fc96a23afnjn#include <mach-o/dyld.h>
53f76d27a697a7b0bf3b84490baf60623fc96a23afnjn#include <mach-o/fat.h>
54f76d27a697a7b0bf3b84490baf60623fc96a23afnjn#include <mach-o/loader.h>
55f76d27a697a7b0bf3b84490baf60623fc96a23afnjn
56f76d27a697a7b0bf3b84490baf60623fc96a23afnjn#if VG_WORDSIZE == 4
57f76d27a697a7b0bf3b84490baf60623fc96a23afnjn#define MAGIC MH_MAGIC
58f76d27a697a7b0bf3b84490baf60623fc96a23afnjn#define MACH_HEADER mach_header
59f76d27a697a7b0bf3b84490baf60623fc96a23afnjn#define LC_SEGMENT_CMD LC_SEGMENT
60f76d27a697a7b0bf3b84490baf60623fc96a23afnjn#define SEGMENT_COMMAND segment_command
61f76d27a697a7b0bf3b84490baf60623fc96a23afnjn#define SECTION section
62f76d27a697a7b0bf3b84490baf60623fc96a23afnjn#else
63f76d27a697a7b0bf3b84490baf60623fc96a23afnjn#define MAGIC MH_MAGIC_64
64f76d27a697a7b0bf3b84490baf60623fc96a23afnjn#define MACH_HEADER mach_header_64
65f76d27a697a7b0bf3b84490baf60623fc96a23afnjn#define LC_SEGMENT_CMD LC_SEGMENT_64
66f76d27a697a7b0bf3b84490baf60623fc96a23afnjn#define SEGMENT_COMMAND segment_command_64
67f76d27a697a7b0bf3b84490baf60623fc96a23afnjn#define SECTION section_64
68f76d27a697a7b0bf3b84490baf60623fc96a23afnjn#endif
69f76d27a697a7b0bf3b84490baf60623fc96a23afnjn
70f76d27a697a7b0bf3b84490baf60623fc96a23afnjn
710af78adc02d94916ae0d31ffc02e40e3bea11877florianstatic void print(const HChar *str)
72f76d27a697a7b0bf3b84490baf60623fc96a23afnjn{
73f76d27a697a7b0bf3b84490baf60623fc96a23afnjn   VG_(printf)("%s", str);
74f76d27a697a7b0bf3b84490baf60623fc96a23afnjn}
75f76d27a697a7b0bf3b84490baf60623fc96a23afnjn
76e07cbb30f8a773e75d01d8b5aa05fb328974695eflorianstatic void check_mmap(SysRes res, Addr base, SizeT len, const HChar* who)
77f76d27a697a7b0bf3b84490baf60623fc96a23afnjn{
78f76d27a697a7b0bf3b84490baf60623fc96a23afnjn   if (sr_isError(res)) {
79f0c855fac3f394b3fad9c0d15d86381b4073e164rhyskidd      VG_(printf)("valgrind: mmap-FIXED(0x%llx, %lld) failed in UME (%s) "
80f0c855fac3f394b3fad9c0d15d86381b4073e164rhyskidd                  "with error %lu (%s).\n",
81f0c855fac3f394b3fad9c0d15d86381b4073e164rhyskidd                  (ULong)base, (Long)len, who,
82f0c855fac3f394b3fad9c0d15d86381b4073e164rhyskidd                  sr_Err(res), VG_(strerror)(sr_Err(res)) );
83f76d27a697a7b0bf3b84490baf60623fc96a23afnjn      VG_(exit)(1);
84f76d27a697a7b0bf3b84490baf60623fc96a23afnjn   }
85f76d27a697a7b0bf3b84490baf60623fc96a23afnjn}
86f76d27a697a7b0bf3b84490baf60623fc96a23afnjn
87ec66ad5f33a4d904b1f728935ec6ee29b58a55ecsewardj#if DARWIN_VERS >= DARWIN_10_8
88e07cbb30f8a773e75d01d8b5aa05fb328974695eflorianstatic void check_mmap_float(SysRes res, SizeT len, const HChar* who)
89ae284e5cc0830afcdec7b436564ea9f18bbedff8sewardj{
90ae284e5cc0830afcdec7b436564ea9f18bbedff8sewardj   if (sr_isError(res)) {
91f0c855fac3f394b3fad9c0d15d86381b4073e164rhyskidd      VG_(printf)("valgrind: mmap-FLOAT(size=%lld) failed in UME (%s) "
92f0c855fac3f394b3fad9c0d15d86381b4073e164rhyskidd                  "with error %lu (%s).\n",
93f0c855fac3f394b3fad9c0d15d86381b4073e164rhyskidd                  (Long)len, who,
94f0c855fac3f394b3fad9c0d15d86381b4073e164rhyskidd                  sr_Err(res), VG_(strerror)(sr_Err(res)) );
95ae284e5cc0830afcdec7b436564ea9f18bbedff8sewardj      VG_(exit)(1);
96ae284e5cc0830afcdec7b436564ea9f18bbedff8sewardj   }
97ae284e5cc0830afcdec7b436564ea9f18bbedff8sewardj}
98bb5d4c6348b24ddec78725139c28010ea30bac92sewardj#endif
99f76d27a697a7b0bf3b84490baf60623fc96a23afnjn
100f76d27a697a7b0bf3b84490baf60623fc96a23afnjnstatic int
101f76d27a697a7b0bf3b84490baf60623fc96a23afnjnload_thin_file(int fd, vki_off_t offset, vki_off_t size, unsigned long filetype,
1020af78adc02d94916ae0d31ffc02e40e3bea11877florian               const HChar *filename,
103f76d27a697a7b0bf3b84490baf60623fc96a23afnjn               vki_uint8_t **out_stack_start, vki_uint8_t **out_stack_end,
104f76d27a697a7b0bf3b84490baf60623fc96a23afnjn               vki_uint8_t **out_text, vki_uint8_t **out_entry, vki_uint8_t **out_linker_entry);
105f76d27a697a7b0bf3b84490baf60623fc96a23afnjn
106f76d27a697a7b0bf3b84490baf60623fc96a23afnjnstatic int
107f76d27a697a7b0bf3b84490baf60623fc96a23afnjnload_fat_file(int fd, vki_off_t offset, vki_off_t size, unsigned long filetype,
1080af78adc02d94916ae0d31ffc02e40e3bea11877florian              const HChar *filename,
109f76d27a697a7b0bf3b84490baf60623fc96a23afnjn              vki_uint8_t **out_stack_start, vki_uint8_t **out_stack_end,
110f76d27a697a7b0bf3b84490baf60623fc96a23afnjn              vki_uint8_t **out_text, vki_uint8_t **out_entry, vki_uint8_t **out_linker_entry);
111f76d27a697a7b0bf3b84490baf60623fc96a23afnjn
112f76d27a697a7b0bf3b84490baf60623fc96a23afnjnstatic int
113f76d27a697a7b0bf3b84490baf60623fc96a23afnjnload_mach_file(int fd, vki_off_t offset, vki_off_t size, unsigned long filetype,
1140af78adc02d94916ae0d31ffc02e40e3bea11877florian               const HChar *filename,
115f76d27a697a7b0bf3b84490baf60623fc96a23afnjn               vki_uint8_t **out_stack_start, vki_uint8_t **out_stack_end,
116f76d27a697a7b0bf3b84490baf60623fc96a23afnjn               vki_uint8_t **out_text, vki_uint8_t **out_entry, vki_uint8_t **out_linker_entry);
117f76d27a697a7b0bf3b84490baf60623fc96a23afnjn
118f76d27a697a7b0bf3b84490baf60623fc96a23afnjn
119f76d27a697a7b0bf3b84490baf60623fc96a23afnjn/* Open and map a dylinker file.
120f76d27a697a7b0bf3b84490baf60623fc96a23afnjn   Returns 0 on success, -1 on any failure.
121f76d27a697a7b0bf3b84490baf60623fc96a23afnjn   filename must be an absolute path.
122f76d27a697a7b0bf3b84490baf60623fc96a23afnjn   The dylinker's entry point is returned in *out_linker_entry.
123f76d27a697a7b0bf3b84490baf60623fc96a23afnjn */
124f76d27a697a7b0bf3b84490baf60623fc96a23afnjnstatic int
1250af78adc02d94916ae0d31ffc02e40e3bea11877florianopen_dylinker(const HChar *filename, vki_uint8_t **out_linker_entry)
126f76d27a697a7b0bf3b84490baf60623fc96a23afnjn{
127f76d27a697a7b0bf3b84490baf60623fc96a23afnjn   struct vg_stat sb;
128f76d27a697a7b0bf3b84490baf60623fc96a23afnjn   vki_size_t filesize;
129f76d27a697a7b0bf3b84490baf60623fc96a23afnjn   SysRes res;
130f76d27a697a7b0bf3b84490baf60623fc96a23afnjn   int fd;
131f76d27a697a7b0bf3b84490baf60623fc96a23afnjn   int err;
132f76d27a697a7b0bf3b84490baf60623fc96a23afnjn
133f76d27a697a7b0bf3b84490baf60623fc96a23afnjn   if (filename[0] != '/') {
134f76d27a697a7b0bf3b84490baf60623fc96a23afnjn      print("bad executable (dylinker name is not an absolute path)\n");
135f76d27a697a7b0bf3b84490baf60623fc96a23afnjn      return -1;
136f76d27a697a7b0bf3b84490baf60623fc96a23afnjn   }
137f76d27a697a7b0bf3b84490baf60623fc96a23afnjn
138f76d27a697a7b0bf3b84490baf60623fc96a23afnjn   res = VG_(open)(filename, VKI_O_RDONLY, 0);
139f76d27a697a7b0bf3b84490baf60623fc96a23afnjn   fd = sr_Res(res);
140f76d27a697a7b0bf3b84490baf60623fc96a23afnjn   if (sr_isError(res)) {
141f76d27a697a7b0bf3b84490baf60623fc96a23afnjn      print("couldn't open dylinker: ");
142f76d27a697a7b0bf3b84490baf60623fc96a23afnjn      print(filename);
143f76d27a697a7b0bf3b84490baf60623fc96a23afnjn      print("\n");
144f76d27a697a7b0bf3b84490baf60623fc96a23afnjn      return -1;
145f76d27a697a7b0bf3b84490baf60623fc96a23afnjn   }
146f76d27a697a7b0bf3b84490baf60623fc96a23afnjn   err = VG_(fstat)(fd, &sb);
147f76d27a697a7b0bf3b84490baf60623fc96a23afnjn   if (err) {
148f76d27a697a7b0bf3b84490baf60623fc96a23afnjn      print("couldn't stat dylinker: ");
149f76d27a697a7b0bf3b84490baf60623fc96a23afnjn      print(filename);
150f76d27a697a7b0bf3b84490baf60623fc96a23afnjn      print("\n");
151f76d27a697a7b0bf3b84490baf60623fc96a23afnjn      VG_(close)(fd);
152f76d27a697a7b0bf3b84490baf60623fc96a23afnjn      return -1;
153f76d27a697a7b0bf3b84490baf60623fc96a23afnjn   }
154f76d27a697a7b0bf3b84490baf60623fc96a23afnjn   filesize = sb.size;
155f76d27a697a7b0bf3b84490baf60623fc96a23afnjn
156f76d27a697a7b0bf3b84490baf60623fc96a23afnjn   err = load_mach_file(fd, 0, filesize, MH_DYLINKER, filename,
157f76d27a697a7b0bf3b84490baf60623fc96a23afnjn                        NULL, NULL, NULL, out_linker_entry, NULL);
158f76d27a697a7b0bf3b84490baf60623fc96a23afnjn   if (err) {
159f76d27a697a7b0bf3b84490baf60623fc96a23afnjn      print("...while loading dylinker: ");
160f76d27a697a7b0bf3b84490baf60623fc96a23afnjn      print(filename);
161f76d27a697a7b0bf3b84490baf60623fc96a23afnjn      print("\n");
162f76d27a697a7b0bf3b84490baf60623fc96a23afnjn   }
163f76d27a697a7b0bf3b84490baf60623fc96a23afnjn   VG_(close)(fd);
164f76d27a697a7b0bf3b84490baf60623fc96a23afnjn   return err;
165f76d27a697a7b0bf3b84490baf60623fc96a23afnjn}
166f76d27a697a7b0bf3b84490baf60623fc96a23afnjn
167f76d27a697a7b0bf3b84490baf60623fc96a23afnjn
168f76d27a697a7b0bf3b84490baf60623fc96a23afnjn/*
169f76d27a697a7b0bf3b84490baf60623fc96a23afnjn   Process an LC_SEGMENT command, mapping it into memory if appropriate.
170f76d27a697a7b0bf3b84490baf60623fc96a23afnjn   fd[offset..size) is a Mach-O thin file.
171f76d27a697a7b0bf3b84490baf60623fc96a23afnjn   Returns 0 on success, -1 on any failure.
172f76d27a697a7b0bf3b84490baf60623fc96a23afnjn   If this segment contains the executable's Mach headers, their
173f76d27a697a7b0bf3b84490baf60623fc96a23afnjn     loaded address is returned in *text.
174f76d27a697a7b0bf3b84490baf60623fc96a23afnjn   If this segment is a __UNIXSTACK, its start address is returned in
175f76d27a697a7b0bf3b84490baf60623fc96a23afnjn     *stack_start.
176f76d27a697a7b0bf3b84490baf60623fc96a23afnjn*/
177f76d27a697a7b0bf3b84490baf60623fc96a23afnjnstatic int
178f76d27a697a7b0bf3b84490baf60623fc96a23afnjnload_segment(int fd, vki_off_t offset, vki_off_t size,
179f76d27a697a7b0bf3b84490baf60623fc96a23afnjn             vki_uint8_t **text, vki_uint8_t **stack_start,
180f76d27a697a7b0bf3b84490baf60623fc96a23afnjn             struct SEGMENT_COMMAND *segcmd, const HChar *filename)
181f76d27a697a7b0bf3b84490baf60623fc96a23afnjn{
182f76d27a697a7b0bf3b84490baf60623fc96a23afnjn   SysRes res;
183f76d27a697a7b0bf3b84490baf60623fc96a23afnjn   Addr addr;
184f76d27a697a7b0bf3b84490baf60623fc96a23afnjn   vki_size_t filesize; // page-aligned
185f76d27a697a7b0bf3b84490baf60623fc96a23afnjn   vki_size_t vmsize;   // page-aligned
186f76d27a697a7b0bf3b84490baf60623fc96a23afnjn   unsigned int prot;
187f76d27a697a7b0bf3b84490baf60623fc96a23afnjn
188f76d27a697a7b0bf3b84490baf60623fc96a23afnjn   // GrP fixme mark __UNIXSTACK as SF_STACK
189f76d27a697a7b0bf3b84490baf60623fc96a23afnjn
190ea2d6fd6aaf98d261df9fdf580542ebf01b7fba4njn   // Don't honour the client's request to map PAGEZERO.  Why not?
191ea2d6fd6aaf98d261df9fdf580542ebf01b7fba4njn   // Because when the kernel loaded the valgrind tool executable,
192ea2d6fd6aaf98d261df9fdf580542ebf01b7fba4njn   // it will have mapped pagezero itself.  So further attempts
193ea2d6fd6aaf98d261df9fdf580542ebf01b7fba4njn   // to map it when loading the client are guaranteed to fail.
194ea2d6fd6aaf98d261df9fdf580542ebf01b7fba4njn#if VG_WORDSIZE == 4
195ea2d6fd6aaf98d261df9fdf580542ebf01b7fba4njn   if (segcmd->vmaddr == 0 && 0 == VG_(strcmp)(segcmd->segname, SEG_PAGEZERO)) {
196ea2d6fd6aaf98d261df9fdf580542ebf01b7fba4njn      if (segcmd->vmsize != 0x1000) {
197ea2d6fd6aaf98d261df9fdf580542ebf01b7fba4njn         print("bad executable (__PAGEZERO is not 4 KB)\n");
198ea2d6fd6aaf98d261df9fdf580542ebf01b7fba4njn         return -1;
199ea2d6fd6aaf98d261df9fdf580542ebf01b7fba4njn      }
200ea2d6fd6aaf98d261df9fdf580542ebf01b7fba4njn      return 0;
201ea2d6fd6aaf98d261df9fdf580542ebf01b7fba4njn   }
202ea2d6fd6aaf98d261df9fdf580542ebf01b7fba4njn#endif
203f76d27a697a7b0bf3b84490baf60623fc96a23afnjn#if VG_WORDSIZE == 8
204f76d27a697a7b0bf3b84490baf60623fc96a23afnjn   if (segcmd->vmaddr == 0 && 0 == VG_(strcmp)(segcmd->segname, SEG_PAGEZERO)) {
205f76d27a697a7b0bf3b84490baf60623fc96a23afnjn      if (segcmd->vmsize != 0x100000000) {
206f76d27a697a7b0bf3b84490baf60623fc96a23afnjn         print("bad executable (__PAGEZERO is not 4 GB)\n");
207f76d27a697a7b0bf3b84490baf60623fc96a23afnjn         return -1;
208f76d27a697a7b0bf3b84490baf60623fc96a23afnjn      }
209f76d27a697a7b0bf3b84490baf60623fc96a23afnjn      return 0;
210f76d27a697a7b0bf3b84490baf60623fc96a23afnjn   }
211f76d27a697a7b0bf3b84490baf60623fc96a23afnjn#endif
212f76d27a697a7b0bf3b84490baf60623fc96a23afnjn
213f76d27a697a7b0bf3b84490baf60623fc96a23afnjn   // Record the segment containing the Mach headers themselves
214f76d27a697a7b0bf3b84490baf60623fc96a23afnjn   if (segcmd->fileoff == 0  &&  segcmd->filesize != 0) {
215f76d27a697a7b0bf3b84490baf60623fc96a23afnjn      if (text) *text = (vki_uint8_t *)segcmd->vmaddr;
216f76d27a697a7b0bf3b84490baf60623fc96a23afnjn   }
217f76d27a697a7b0bf3b84490baf60623fc96a23afnjn
218f76d27a697a7b0bf3b84490baf60623fc96a23afnjn   // Record the __UNIXSTACK start
219f76d27a697a7b0bf3b84490baf60623fc96a23afnjn   if (0 == VG_(strcmp)(segcmd->segname, SEG_UNIXSTACK)) {
220f76d27a697a7b0bf3b84490baf60623fc96a23afnjn      if (stack_start) *stack_start = (vki_uint8_t *)segcmd->vmaddr;
221f76d27a697a7b0bf3b84490baf60623fc96a23afnjn   }
222f76d27a697a7b0bf3b84490baf60623fc96a23afnjn
223f76d27a697a7b0bf3b84490baf60623fc96a23afnjn   // Sanity-check the segment
224f76d27a697a7b0bf3b84490baf60623fc96a23afnjn   if (segcmd->fileoff + segcmd->filesize > size) {
225f76d27a697a7b0bf3b84490baf60623fc96a23afnjn      print("bad executable (invalid segment command)\n");
226f76d27a697a7b0bf3b84490baf60623fc96a23afnjn      return -1;
227f76d27a697a7b0bf3b84490baf60623fc96a23afnjn   }
228f76d27a697a7b0bf3b84490baf60623fc96a23afnjn   if (segcmd->vmsize == 0) {
229f76d27a697a7b0bf3b84490baf60623fc96a23afnjn      return 0;  // nothing to map - ok
230f76d27a697a7b0bf3b84490baf60623fc96a23afnjn   }
231f76d27a697a7b0bf3b84490baf60623fc96a23afnjn
232f76d27a697a7b0bf3b84490baf60623fc96a23afnjn   // Get desired memory protection
233f76d27a697a7b0bf3b84490baf60623fc96a23afnjn   // GrP fixme need maxprot too
234f76d27a697a7b0bf3b84490baf60623fc96a23afnjn   prot = (((segcmd->initprot & VM_PROT_READ) ? VKI_PROT_READ : 0) |
235f76d27a697a7b0bf3b84490baf60623fc96a23afnjn           ((segcmd->initprot & VM_PROT_WRITE) ? VKI_PROT_WRITE : 0) |
236f76d27a697a7b0bf3b84490baf60623fc96a23afnjn           ((segcmd->initprot & VM_PROT_EXECUTE) ? VKI_PROT_EXEC : 0));
237f76d27a697a7b0bf3b84490baf60623fc96a23afnjn
238f76d27a697a7b0bf3b84490baf60623fc96a23afnjn   // Map the segment
239f76d27a697a7b0bf3b84490baf60623fc96a23afnjn   filesize = VG_PGROUNDUP(segcmd->filesize);
240f76d27a697a7b0bf3b84490baf60623fc96a23afnjn   vmsize = VG_PGROUNDUP(segcmd->vmsize);
241f76d27a697a7b0bf3b84490baf60623fc96a23afnjn   if (filesize > 0) {
242f76d27a697a7b0bf3b84490baf60623fc96a23afnjn      addr = (Addr)segcmd->vmaddr;
243ea2d6fd6aaf98d261df9fdf580542ebf01b7fba4njn      VG_(debugLog)(2, "ume", "mmap fixed (file) (%#lx, %lu)\n", addr, filesize);
244f76d27a697a7b0bf3b84490baf60623fc96a23afnjn      res = VG_(am_mmap_named_file_fixed_client)(addr, filesize, prot, fd,
245f76d27a697a7b0bf3b84490baf60623fc96a23afnjn                                                 offset + segcmd->fileoff,
246f76d27a697a7b0bf3b84490baf60623fc96a23afnjn                                                 filename);
247ea2d6fd6aaf98d261df9fdf580542ebf01b7fba4njn      check_mmap(res, addr, filesize, "load_segment1");
248f76d27a697a7b0bf3b84490baf60623fc96a23afnjn   }
249f76d27a697a7b0bf3b84490baf60623fc96a23afnjn
250f76d27a697a7b0bf3b84490baf60623fc96a23afnjn   // Zero-fill the remainder of the segment, if any
251f76d27a697a7b0bf3b84490baf60623fc96a23afnjn   if (segcmd->filesize != filesize) {
252f76d27a697a7b0bf3b84490baf60623fc96a23afnjn      // non-page-aligned part
253f76d27a697a7b0bf3b84490baf60623fc96a23afnjn      // GrP fixme kernel doesn't do this?
254f76d27a697a7b0bf3b84490baf60623fc96a23afnjn      //bzero(segcmd->filesize+(vki_uint8_t *)addr, filesize-segcmd->filesize);
255f76d27a697a7b0bf3b84490baf60623fc96a23afnjn   }
256f76d27a697a7b0bf3b84490baf60623fc96a23afnjn   if (filesize != vmsize) {
257f76d27a697a7b0bf3b84490baf60623fc96a23afnjn      // page-aligned part
258f76d27a697a7b0bf3b84490baf60623fc96a23afnjn      SizeT length = vmsize - filesize;
259f76d27a697a7b0bf3b84490baf60623fc96a23afnjn      addr = (Addr)(filesize + segcmd->vmaddr);
260ea2d6fd6aaf98d261df9fdf580542ebf01b7fba4njn      VG_(debugLog)(2, "ume", "mmap fixed (anon) (%#lx, %lu)\n", addr, length);
261f76d27a697a7b0bf3b84490baf60623fc96a23afnjn      res = VG_(am_mmap_anon_fixed_client)(addr, length, prot);
262ea2d6fd6aaf98d261df9fdf580542ebf01b7fba4njn      check_mmap(res, addr, length, "load_segment2");
263f76d27a697a7b0bf3b84490baf60623fc96a23afnjn   }
264f76d27a697a7b0bf3b84490baf60623fc96a23afnjn
265f76d27a697a7b0bf3b84490baf60623fc96a23afnjn   return 0;
266f76d27a697a7b0bf3b84490baf60623fc96a23afnjn}
267f76d27a697a7b0bf3b84490baf60623fc96a23afnjn
268f76d27a697a7b0bf3b84490baf60623fc96a23afnjn
269f76d27a697a7b0bf3b84490baf60623fc96a23afnjn/*
270f76d27a697a7b0bf3b84490baf60623fc96a23afnjn   Parse a LC_THREAD or LC_UNIXTHREAD command.
271f76d27a697a7b0bf3b84490baf60623fc96a23afnjn   Return 0 on success, -1 on any failure.
272f76d27a697a7b0bf3b84490baf60623fc96a23afnjn   The stack address is returned in *stack. If the executable requested
273f76d27a697a7b0bf3b84490baf60623fc96a23afnjn   a non-default stack address, *customstack is set to TRUE. The thread's
274f76d27a697a7b0bf3b84490baf60623fc96a23afnjn   entry point is returned in *entry.
275f76d27a697a7b0bf3b84490baf60623fc96a23afnjn   The stack itself (if any) is not mapped.
276f76d27a697a7b0bf3b84490baf60623fc96a23afnjn   Other custom register settings are silently ignored (GrP fixme).
277f76d27a697a7b0bf3b84490baf60623fc96a23afnjn*/
278f76d27a697a7b0bf3b84490baf60623fc96a23afnjnstatic int
279f76d27a697a7b0bf3b84490baf60623fc96a23afnjnload_genericthread(vki_uint8_t **stack_end,
280f76d27a697a7b0bf3b84490baf60623fc96a23afnjn                   int *customstack, vki_uint8_t **entry,
281f76d27a697a7b0bf3b84490baf60623fc96a23afnjn                   struct thread_command *threadcmd)
282f76d27a697a7b0bf3b84490baf60623fc96a23afnjn{
283f76d27a697a7b0bf3b84490baf60623fc96a23afnjn   unsigned int flavor;
284f76d27a697a7b0bf3b84490baf60623fc96a23afnjn   unsigned int count;
285f76d27a697a7b0bf3b84490baf60623fc96a23afnjn   unsigned int *p;
286f76d27a697a7b0bf3b84490baf60623fc96a23afnjn   unsigned int left;
287f76d27a697a7b0bf3b84490baf60623fc96a23afnjn
288f76d27a697a7b0bf3b84490baf60623fc96a23afnjn   p = (unsigned int *)(threadcmd + 1);
289f76d27a697a7b0bf3b84490baf60623fc96a23afnjn   left = (threadcmd->cmdsize - sizeof(struct thread_command)) / sizeof(*p);
290f76d27a697a7b0bf3b84490baf60623fc96a23afnjn
291f76d27a697a7b0bf3b84490baf60623fc96a23afnjn   while (left > 0) {
292f76d27a697a7b0bf3b84490baf60623fc96a23afnjn      if (left < 2) {
293f76d27a697a7b0bf3b84490baf60623fc96a23afnjn         print("bad executable (invalid thread command)\n");
294f76d27a697a7b0bf3b84490baf60623fc96a23afnjn         return -1;
295f76d27a697a7b0bf3b84490baf60623fc96a23afnjn      }
296f76d27a697a7b0bf3b84490baf60623fc96a23afnjn      flavor = *p++; left--;
297f76d27a697a7b0bf3b84490baf60623fc96a23afnjn      count = *p++; left--;
298f76d27a697a7b0bf3b84490baf60623fc96a23afnjn
299f76d27a697a7b0bf3b84490baf60623fc96a23afnjn      if (left < count) {
300f76d27a697a7b0bf3b84490baf60623fc96a23afnjn         print("bad executable (invalid thread command 2)\n");
301f76d27a697a7b0bf3b84490baf60623fc96a23afnjn         return -1;
302f76d27a697a7b0bf3b84490baf60623fc96a23afnjn      }
303f76d27a697a7b0bf3b84490baf60623fc96a23afnjn
304f76d27a697a7b0bf3b84490baf60623fc96a23afnjn#if defined(VGA_x86)
305f76d27a697a7b0bf3b84490baf60623fc96a23afnjn      if (flavor == i386_THREAD_STATE && count == i386_THREAD_STATE_COUNT) {
306f76d27a697a7b0bf3b84490baf60623fc96a23afnjn         i386_thread_state_t *state = (i386_thread_state_t *)p;
307f76d27a697a7b0bf3b84490baf60623fc96a23afnjn         if (entry) *entry = (vki_uint8_t *)state->__eip;
3086b0cdb0b5afd8ddbdbc7ef87d733fc0b8c7c0fb1sewardj         if (stack_end) {
3096b0cdb0b5afd8ddbdbc7ef87d733fc0b8c7c0fb1sewardj            *stack_end = (vki_uint8_t *)(state->__esp ? state->__esp
3106b0cdb0b5afd8ddbdbc7ef87d733fc0b8c7c0fb1sewardj                                                      : VKI_USRSTACK);
3116b0cdb0b5afd8ddbdbc7ef87d733fc0b8c7c0fb1sewardj            vg_assert(VG_IS_PAGE_ALIGNED(*stack_end));
3126b0cdb0b5afd8ddbdbc7ef87d733fc0b8c7c0fb1sewardj            (*stack_end)--;
3136b0cdb0b5afd8ddbdbc7ef87d733fc0b8c7c0fb1sewardj         }
314f76d27a697a7b0bf3b84490baf60623fc96a23afnjn         if (customstack) *customstack = state->__esp;
315f76d27a697a7b0bf3b84490baf60623fc96a23afnjn         return 0;
316f76d27a697a7b0bf3b84490baf60623fc96a23afnjn      }
317f76d27a697a7b0bf3b84490baf60623fc96a23afnjn
318f76d27a697a7b0bf3b84490baf60623fc96a23afnjn#elif defined(VGA_amd64)
319f76d27a697a7b0bf3b84490baf60623fc96a23afnjn      if (flavor == x86_THREAD_STATE64 && count == x86_THREAD_STATE64_COUNT){
320f76d27a697a7b0bf3b84490baf60623fc96a23afnjn         x86_thread_state64_t *state = (x86_thread_state64_t *)p;
321f76d27a697a7b0bf3b84490baf60623fc96a23afnjn         if (entry) *entry = (vki_uint8_t *)state->__rip;
3226b0cdb0b5afd8ddbdbc7ef87d733fc0b8c7c0fb1sewardj         if (stack_end) {
3236b0cdb0b5afd8ddbdbc7ef87d733fc0b8c7c0fb1sewardj            *stack_end = (vki_uint8_t *)(state->__rsp ? state->__rsp
3246b0cdb0b5afd8ddbdbc7ef87d733fc0b8c7c0fb1sewardj                                                      : VKI_USRSTACK64);
3256b0cdb0b5afd8ddbdbc7ef87d733fc0b8c7c0fb1sewardj            vg_assert(VG_IS_PAGE_ALIGNED(*stack_end));
3266b0cdb0b5afd8ddbdbc7ef87d733fc0b8c7c0fb1sewardj            (*stack_end)--;
3276b0cdb0b5afd8ddbdbc7ef87d733fc0b8c7c0fb1sewardj         }
328f76d27a697a7b0bf3b84490baf60623fc96a23afnjn         if (customstack) *customstack = state->__rsp;
329f76d27a697a7b0bf3b84490baf60623fc96a23afnjn         return 0;
330f76d27a697a7b0bf3b84490baf60623fc96a23afnjn      }
331f76d27a697a7b0bf3b84490baf60623fc96a23afnjn
332f76d27a697a7b0bf3b84490baf60623fc96a23afnjn#else
333f76d27a697a7b0bf3b84490baf60623fc96a23afnjn# error unknown platform
334f76d27a697a7b0bf3b84490baf60623fc96a23afnjn#endif
335f76d27a697a7b0bf3b84490baf60623fc96a23afnjn      p += count;
336f76d27a697a7b0bf3b84490baf60623fc96a23afnjn      left -= count;
337f76d27a697a7b0bf3b84490baf60623fc96a23afnjn   }
338f76d27a697a7b0bf3b84490baf60623fc96a23afnjn
339f76d27a697a7b0bf3b84490baf60623fc96a23afnjn   print("bad executable (no arch-compatible thread state)\n");
340f76d27a697a7b0bf3b84490baf60623fc96a23afnjn   return -1;
341f76d27a697a7b0bf3b84490baf60623fc96a23afnjn}
342f76d27a697a7b0bf3b84490baf60623fc96a23afnjn
343f76d27a697a7b0bf3b84490baf60623fc96a23afnjn
344f76d27a697a7b0bf3b84490baf60623fc96a23afnjn/* Returns the main stack size on this platform,
345f76d27a697a7b0bf3b84490baf60623fc96a23afnjn   using getrlimit or a fixed size.
346f76d27a697a7b0bf3b84490baf60623fc96a23afnjn   GrP fixme 64-bit? */
347f76d27a697a7b0bf3b84490baf60623fc96a23afnjnstatic vki_size_t default_stack_size(void)
348f76d27a697a7b0bf3b84490baf60623fc96a23afnjn{
349f76d27a697a7b0bf3b84490baf60623fc96a23afnjn   struct vki_rlimit lim;
350f76d27a697a7b0bf3b84490baf60623fc96a23afnjn   int err = VG_(getrlimit)(VKI_RLIMIT_STACK, &lim);
351f76d27a697a7b0bf3b84490baf60623fc96a23afnjn   if (err) return 8*1024*1024; // 8 MB
352f76d27a697a7b0bf3b84490baf60623fc96a23afnjn   else return lim.rlim_cur;
353f76d27a697a7b0bf3b84490baf60623fc96a23afnjn}
354f76d27a697a7b0bf3b84490baf60623fc96a23afnjn
355f76d27a697a7b0bf3b84490baf60623fc96a23afnjn
356f76d27a697a7b0bf3b84490baf60623fc96a23afnjn/*
357f76d27a697a7b0bf3b84490baf60623fc96a23afnjn   Processes a LC_UNIXTHREAD command.
358f76d27a697a7b0bf3b84490baf60623fc96a23afnjn   Returns 0 on success, -1 on any failure.
359f76d27a697a7b0bf3b84490baf60623fc96a23afnjn   The stack is mapped in and returned in *out_stack.
360f76d27a697a7b0bf3b84490baf60623fc96a23afnjn   The thread's entry point is returned in *out_entry.
361f76d27a697a7b0bf3b84490baf60623fc96a23afnjn*/
362f76d27a697a7b0bf3b84490baf60623fc96a23afnjnstatic int
363f76d27a697a7b0bf3b84490baf60623fc96a23afnjnload_unixthread(vki_uint8_t **out_stack_start, vki_uint8_t **out_stack_end,
364f76d27a697a7b0bf3b84490baf60623fc96a23afnjn                vki_uint8_t **out_entry, struct thread_command *threadcmd)
365f76d27a697a7b0bf3b84490baf60623fc96a23afnjn{
366f76d27a697a7b0bf3b84490baf60623fc96a23afnjn   int err;
367f76d27a697a7b0bf3b84490baf60623fc96a23afnjn   vki_uint8_t *stack_end;
368f76d27a697a7b0bf3b84490baf60623fc96a23afnjn   int customstack;
369f76d27a697a7b0bf3b84490baf60623fc96a23afnjn
370f76d27a697a7b0bf3b84490baf60623fc96a23afnjn   err = load_genericthread(&stack_end, &customstack, out_entry, threadcmd);
371f76d27a697a7b0bf3b84490baf60623fc96a23afnjn   if (err) return -1;
372f76d27a697a7b0bf3b84490baf60623fc96a23afnjn
373f76d27a697a7b0bf3b84490baf60623fc96a23afnjn   if (!stack_end) {
374f76d27a697a7b0bf3b84490baf60623fc96a23afnjn      print("bad executable (no thread stack)\n");
375f76d27a697a7b0bf3b84490baf60623fc96a23afnjn      return -1;
376f76d27a697a7b0bf3b84490baf60623fc96a23afnjn   }
377f76d27a697a7b0bf3b84490baf60623fc96a23afnjn
378f76d27a697a7b0bf3b84490baf60623fc96a23afnjn   if (!customstack) {
379f76d27a697a7b0bf3b84490baf60623fc96a23afnjn      // Map the stack
380f76d27a697a7b0bf3b84490baf60623fc96a23afnjn      vki_size_t stacksize = VG_PGROUNDUP(default_stack_size());
3816b0cdb0b5afd8ddbdbc7ef87d733fc0b8c7c0fb1sewardj      vm_address_t stackbase = VG_PGROUNDDN(stack_end+1-stacksize);
382f76d27a697a7b0bf3b84490baf60623fc96a23afnjn      SysRes res;
383f76d27a697a7b0bf3b84490baf60623fc96a23afnjn
384f76d27a697a7b0bf3b84490baf60623fc96a23afnjn      res = VG_(am_mmap_anon_fixed_client)(stackbase, stacksize, VKI_PROT_READ|VKI_PROT_WRITE|VKI_PROT_EXEC);
385ea2d6fd6aaf98d261df9fdf580542ebf01b7fba4njn      check_mmap(res, stackbase, stacksize, "load_unixthread1");
386f76d27a697a7b0bf3b84490baf60623fc96a23afnjn      if (out_stack_start) *out_stack_start = (vki_uint8_t *)stackbase;
387f76d27a697a7b0bf3b84490baf60623fc96a23afnjn   } else {
388f76d27a697a7b0bf3b84490baf60623fc96a23afnjn      // custom stack - mapped via __UNIXTHREAD segment
389f76d27a697a7b0bf3b84490baf60623fc96a23afnjn   }
390f76d27a697a7b0bf3b84490baf60623fc96a23afnjn
391f76d27a697a7b0bf3b84490baf60623fc96a23afnjn   if (out_stack_end) *out_stack_end = stack_end;
392f76d27a697a7b0bf3b84490baf60623fc96a23afnjn
393f76d27a697a7b0bf3b84490baf60623fc96a23afnjn   return 0;
394f76d27a697a7b0bf3b84490baf60623fc96a23afnjn}
395f76d27a697a7b0bf3b84490baf60623fc96a23afnjn
396f76d27a697a7b0bf3b84490baf60623fc96a23afnjn
397ae284e5cc0830afcdec7b436564ea9f18bbedff8sewardj/* Allocates a stack mapping at a V-chosen address.  Pertains to
398ae284e5cc0830afcdec7b436564ea9f18bbedff8sewardj   LC_MAIN commands, which seem to have appeared in OSX 10.8.
399ae284e5cc0830afcdec7b436564ea9f18bbedff8sewardj
400ae284e5cc0830afcdec7b436564ea9f18bbedff8sewardj   This is a really nasty hack -- allocates 64M+stack size, then
401ae284e5cc0830afcdec7b436564ea9f18bbedff8sewardj   deallocates the 64M, to guarantee that the stack is at least 64M
402ae284e5cc0830afcdec7b436564ea9f18bbedff8sewardj   above zero. */
403ec66ad5f33a4d904b1f728935ec6ee29b58a55ecsewardj#if DARWIN_VERS >= DARWIN_10_8
404ae284e5cc0830afcdec7b436564ea9f18bbedff8sewardjstatic int
405ae284e5cc0830afcdec7b436564ea9f18bbedff8sewardjhandle_lcmain ( vki_uint8_t **out_stack_start,
406ae284e5cc0830afcdec7b436564ea9f18bbedff8sewardj                vki_uint8_t **out_stack_end,
407ae284e5cc0830afcdec7b436564ea9f18bbedff8sewardj                vki_size_t requested_size )
408ae284e5cc0830afcdec7b436564ea9f18bbedff8sewardj{
409ae284e5cc0830afcdec7b436564ea9f18bbedff8sewardj   if (requested_size == 0) {
410ae284e5cc0830afcdec7b436564ea9f18bbedff8sewardj      requested_size = default_stack_size();
411ae284e5cc0830afcdec7b436564ea9f18bbedff8sewardj   }
412ae284e5cc0830afcdec7b436564ea9f18bbedff8sewardj   requested_size = VG_PGROUNDUP(requested_size);
413ae284e5cc0830afcdec7b436564ea9f18bbedff8sewardj
414ae284e5cc0830afcdec7b436564ea9f18bbedff8sewardj   const vki_size_t HACK = 64 * 1024 * 1024;
415ae284e5cc0830afcdec7b436564ea9f18bbedff8sewardj   requested_size += HACK;
416ae284e5cc0830afcdec7b436564ea9f18bbedff8sewardj
417ae284e5cc0830afcdec7b436564ea9f18bbedff8sewardj   SysRes res = VG_(am_mmap_anon_float_client)(requested_size,
418ae284e5cc0830afcdec7b436564ea9f18bbedff8sewardj                   VKI_PROT_READ|VKI_PROT_WRITE|VKI_PROT_EXEC);
419ae284e5cc0830afcdec7b436564ea9f18bbedff8sewardj   check_mmap_float(res, requested_size, "handle_lcmain");
420ae284e5cc0830afcdec7b436564ea9f18bbedff8sewardj   vg_assert(!sr_isError(res));
421ae284e5cc0830afcdec7b436564ea9f18bbedff8sewardj   *out_stack_start = (vki_uint8_t*)sr_Res(res);
422b7dfa58bd482b84b58df5459c7fb427b94ba99a7sewardj   *out_stack_end   = *out_stack_start + requested_size - 1;
423ae284e5cc0830afcdec7b436564ea9f18bbedff8sewardj
424ae284e5cc0830afcdec7b436564ea9f18bbedff8sewardj   Bool need_discard = False;
425ae284e5cc0830afcdec7b436564ea9f18bbedff8sewardj   res = VG_(am_munmap_client)(&need_discard, (Addr)*out_stack_start, HACK);
426ae284e5cc0830afcdec7b436564ea9f18bbedff8sewardj   if (sr_isError(res)) return -1;
427ae284e5cc0830afcdec7b436564ea9f18bbedff8sewardj   vg_assert(!need_discard); // True == wtf?
428ae284e5cc0830afcdec7b436564ea9f18bbedff8sewardj
429ae284e5cc0830afcdec7b436564ea9f18bbedff8sewardj   *out_stack_start += HACK;
430ae284e5cc0830afcdec7b436564ea9f18bbedff8sewardj
431ae284e5cc0830afcdec7b436564ea9f18bbedff8sewardj   return 0;
432ae284e5cc0830afcdec7b436564ea9f18bbedff8sewardj}
433ec66ad5f33a4d904b1f728935ec6ee29b58a55ecsewardj#endif /* DARWIN_VERS >= DARWIN_10_8 */
434ae284e5cc0830afcdec7b436564ea9f18bbedff8sewardj
435ae284e5cc0830afcdec7b436564ea9f18bbedff8sewardj
436ae284e5cc0830afcdec7b436564ea9f18bbedff8sewardj
437f76d27a697a7b0bf3b84490baf60623fc96a23afnjn/*
438f76d27a697a7b0bf3b84490baf60623fc96a23afnjn   Processes an LC_LOAD_DYLINKER command.
439f76d27a697a7b0bf3b84490baf60623fc96a23afnjn   Returns 0 on success, -1 on any error.
440f76d27a697a7b0bf3b84490baf60623fc96a23afnjn   The linker itself is mapped into memory.
441f76d27a697a7b0bf3b84490baf60623fc96a23afnjn   The linker's entry point is returned in *linker_entry.
442f76d27a697a7b0bf3b84490baf60623fc96a23afnjn*/
443f76d27a697a7b0bf3b84490baf60623fc96a23afnjnstatic int
444f76d27a697a7b0bf3b84490baf60623fc96a23afnjnload_dylinker(vki_uint8_t **linker_entry, struct dylinker_command *dycmd)
445f76d27a697a7b0bf3b84490baf60623fc96a23afnjn{
4460af78adc02d94916ae0d31ffc02e40e3bea11877florian   const HChar *name;
447f76d27a697a7b0bf3b84490baf60623fc96a23afnjn
448f76d27a697a7b0bf3b84490baf60623fc96a23afnjn   if (dycmd->name.offset >= dycmd->cmdsize) {
449f76d27a697a7b0bf3b84490baf60623fc96a23afnjn      print("bad executable (invalid dylinker command)\n");
450f76d27a697a7b0bf3b84490baf60623fc96a23afnjn      return -1;
451f76d27a697a7b0bf3b84490baf60623fc96a23afnjn   }
452f76d27a697a7b0bf3b84490baf60623fc96a23afnjn
4530af78adc02d94916ae0d31ffc02e40e3bea11877florian   name = dycmd->name.offset + (HChar *)dycmd;
454f76d27a697a7b0bf3b84490baf60623fc96a23afnjn
455f76d27a697a7b0bf3b84490baf60623fc96a23afnjn   // GrP fixme assumes name is terminated somewhere
456f76d27a697a7b0bf3b84490baf60623fc96a23afnjn   return open_dylinker(name, linker_entry);
457f76d27a697a7b0bf3b84490baf60623fc96a23afnjn}
458f76d27a697a7b0bf3b84490baf60623fc96a23afnjn
459f76d27a697a7b0bf3b84490baf60623fc96a23afnjn
460f76d27a697a7b0bf3b84490baf60623fc96a23afnjn/*
461f76d27a697a7b0bf3b84490baf60623fc96a23afnjn    Process an LC_THREAD command.
462f76d27a697a7b0bf3b84490baf60623fc96a23afnjn    Returns 0 on success, -1 on any failure.
463f76d27a697a7b0bf3b84490baf60623fc96a23afnjn    The thread's entry point is returned in *out_entry.
464f76d27a697a7b0bf3b84490baf60623fc96a23afnjn*/
465f76d27a697a7b0bf3b84490baf60623fc96a23afnjnstatic int
466f76d27a697a7b0bf3b84490baf60623fc96a23afnjnload_thread(vki_uint8_t **out_entry, struct thread_command *threadcmd)
467f76d27a697a7b0bf3b84490baf60623fc96a23afnjn{
468f76d27a697a7b0bf3b84490baf60623fc96a23afnjn   int customstack;
469f76d27a697a7b0bf3b84490baf60623fc96a23afnjn   int err;
470f76d27a697a7b0bf3b84490baf60623fc96a23afnjn
471f76d27a697a7b0bf3b84490baf60623fc96a23afnjn   err = load_genericthread(NULL, &customstack, out_entry, threadcmd);
472f76d27a697a7b0bf3b84490baf60623fc96a23afnjn   if (err) return -1;
473f76d27a697a7b0bf3b84490baf60623fc96a23afnjn   if (customstack) {
474f76d27a697a7b0bf3b84490baf60623fc96a23afnjn      print("bad executable (stackless thread has stack)\n");
475f76d27a697a7b0bf3b84490baf60623fc96a23afnjn      return -1;
476f76d27a697a7b0bf3b84490baf60623fc96a23afnjn   }
477f76d27a697a7b0bf3b84490baf60623fc96a23afnjn   return 0;
478f76d27a697a7b0bf3b84490baf60623fc96a23afnjn}
479f76d27a697a7b0bf3b84490baf60623fc96a23afnjn
480f76d27a697a7b0bf3b84490baf60623fc96a23afnjn
481f76d27a697a7b0bf3b84490baf60623fc96a23afnjn/*
482f76d27a697a7b0bf3b84490baf60623fc96a23afnjn  Loads a Mach-O executable into memory, along with any threads,
483f76d27a697a7b0bf3b84490baf60623fc96a23afnjn  stacks, and dylinker.
484f76d27a697a7b0bf3b84490baf60623fc96a23afnjn  Returns 0 on success, -1 on any failure.
485f76d27a697a7b0bf3b84490baf60623fc96a23afnjn  fd[offset..offset+size) is a Mach-O thin file.
486f76d27a697a7b0bf3b84490baf60623fc96a23afnjn  filetype is MH_EXECUTE or MH_DYLINKER.
487f76d27a697a7b0bf3b84490baf60623fc96a23afnjn  The mapped but empty stack is returned in *out_stack.
488f76d27a697a7b0bf3b84490baf60623fc96a23afnjn  The executable's Mach headers are returned in *out_text.
489f76d27a697a7b0bf3b84490baf60623fc96a23afnjn  The executable's entry point is returned in *out_entry.
490f76d27a697a7b0bf3b84490baf60623fc96a23afnjn  The dylinker's entry point (if any) is returned in *out_linker_entry.
491f76d27a697a7b0bf3b84490baf60623fc96a23afnjn  GrP fixme need to return whether dylinker was found - stack layout is different
492f76d27a697a7b0bf3b84490baf60623fc96a23afnjn*/
493f76d27a697a7b0bf3b84490baf60623fc96a23afnjnstatic int
494f76d27a697a7b0bf3b84490baf60623fc96a23afnjnload_thin_file(int fd, vki_off_t offset, vki_off_t size, unsigned long filetype,
4950af78adc02d94916ae0d31ffc02e40e3bea11877florian               const HChar *filename,
496f76d27a697a7b0bf3b84490baf60623fc96a23afnjn               vki_uint8_t **out_stack_start, vki_uint8_t **out_stack_end,
497f76d27a697a7b0bf3b84490baf60623fc96a23afnjn               vki_uint8_t **out_text, vki_uint8_t **out_entry, vki_uint8_t **out_linker_entry)
498f76d27a697a7b0bf3b84490baf60623fc96a23afnjn{
499ae284e5cc0830afcdec7b436564ea9f18bbedff8sewardj   VG_(debugLog)(1, "ume", "load_thin_file: begin:   %s\n", filename);
500f76d27a697a7b0bf3b84490baf60623fc96a23afnjn   struct MACH_HEADER mh;
501f76d27a697a7b0bf3b84490baf60623fc96a23afnjn   vki_uint8_t *headers;
502f76d27a697a7b0bf3b84490baf60623fc96a23afnjn   vki_uint8_t *headers_end;
503f76d27a697a7b0bf3b84490baf60623fc96a23afnjn   struct load_command *lc;
504f76d27a697a7b0bf3b84490baf60623fc96a23afnjn   struct load_command *lcend;
505f76d27a697a7b0bf3b84490baf60623fc96a23afnjn   struct SEGMENT_COMMAND *segcmd;
506f76d27a697a7b0bf3b84490baf60623fc96a23afnjn   struct thread_command *threadcmd;
507f76d27a697a7b0bf3b84490baf60623fc96a23afnjn   struct dylinker_command *dycmd;
508f76d27a697a7b0bf3b84490baf60623fc96a23afnjn   int err;
509f76d27a697a7b0bf3b84490baf60623fc96a23afnjn   SysRes res;
510f76d27a697a7b0bf3b84490baf60623fc96a23afnjn   vki_size_t len;
511f76d27a697a7b0bf3b84490baf60623fc96a23afnjn
512f76d27a697a7b0bf3b84490baf60623fc96a23afnjn   vki_uint8_t *stack_start = NULL;   // allocated thread stack (hot end)
513f76d27a697a7b0bf3b84490baf60623fc96a23afnjn   vki_uint8_t *stack_end = NULL;   // allocated thread stack (cold end)
514f76d27a697a7b0bf3b84490baf60623fc96a23afnjn   vki_uint8_t *entry = NULL;   // static entry point
515f76d27a697a7b0bf3b84490baf60623fc96a23afnjn   vki_uint8_t *text = NULL;    // start of text segment (i.e. the mach headers)
516f76d27a697a7b0bf3b84490baf60623fc96a23afnjn   vki_uint8_t *linker_entry = NULL; // dylinker entry point
517f76d27a697a7b0bf3b84490baf60623fc96a23afnjn
518f76d27a697a7b0bf3b84490baf60623fc96a23afnjn   // Read Mach-O header
519f76d27a697a7b0bf3b84490baf60623fc96a23afnjn   if (sizeof(mh) > size) {
520f76d27a697a7b0bf3b84490baf60623fc96a23afnjn      print("bad executable (no Mach-O header)\n");
521f76d27a697a7b0bf3b84490baf60623fc96a23afnjn   }
522f76d27a697a7b0bf3b84490baf60623fc96a23afnjn   res = VG_(pread)(fd, &mh, sizeof(mh), offset);
523f76d27a697a7b0bf3b84490baf60623fc96a23afnjn   if (sr_isError(res)  ||  sr_Res(res) != sizeof(mh)) {
524f76d27a697a7b0bf3b84490baf60623fc96a23afnjn      print("bad executable (no Mach-O header)\n");
525f76d27a697a7b0bf3b84490baf60623fc96a23afnjn      return -1;
526f76d27a697a7b0bf3b84490baf60623fc96a23afnjn   }
527f76d27a697a7b0bf3b84490baf60623fc96a23afnjn
528f76d27a697a7b0bf3b84490baf60623fc96a23afnjn
529f76d27a697a7b0bf3b84490baf60623fc96a23afnjn   // Sanity-check the header itself
530f76d27a697a7b0bf3b84490baf60623fc96a23afnjn   if (mh.magic != MAGIC) {
531f76d27a697a7b0bf3b84490baf60623fc96a23afnjn      print("bad executable (no Mach-O magic)\n");
532f76d27a697a7b0bf3b84490baf60623fc96a23afnjn      return -1;
533f76d27a697a7b0bf3b84490baf60623fc96a23afnjn   }
534f76d27a697a7b0bf3b84490baf60623fc96a23afnjn
535f76d27a697a7b0bf3b84490baf60623fc96a23afnjn   if (mh.filetype != filetype) {
536f76d27a697a7b0bf3b84490baf60623fc96a23afnjn      // expecting MH_EXECUTE or MH_DYLINKER
537f76d27a697a7b0bf3b84490baf60623fc96a23afnjn      print("bad executable (wrong file type)\n");
538f76d27a697a7b0bf3b84490baf60623fc96a23afnjn      return -1;
539f76d27a697a7b0bf3b84490baf60623fc96a23afnjn   }
540f76d27a697a7b0bf3b84490baf60623fc96a23afnjn
541f76d27a697a7b0bf3b84490baf60623fc96a23afnjn
542f76d27a697a7b0bf3b84490baf60623fc96a23afnjn   // Map all headers into memory
543f76d27a697a7b0bf3b84490baf60623fc96a23afnjn   len = sizeof(mh) + mh.sizeofcmds;
544f76d27a697a7b0bf3b84490baf60623fc96a23afnjn   if (len > size) {
545f76d27a697a7b0bf3b84490baf60623fc96a23afnjn      print("bad executable (missing load commands)\n");
546f76d27a697a7b0bf3b84490baf60623fc96a23afnjn      return -1;
547f76d27a697a7b0bf3b84490baf60623fc96a23afnjn   }
548f76d27a697a7b0bf3b84490baf60623fc96a23afnjn
549f76d27a697a7b0bf3b84490baf60623fc96a23afnjn   headers = VG_(malloc)("ume.macho.headers", len);
550f76d27a697a7b0bf3b84490baf60623fc96a23afnjn   res = VG_(pread)(fd, headers, len, offset);
551f76d27a697a7b0bf3b84490baf60623fc96a23afnjn   if (sr_isError(res)) {
552f76d27a697a7b0bf3b84490baf60623fc96a23afnjn      print("couldn't read load commands from executable\n");
553f76d27a697a7b0bf3b84490baf60623fc96a23afnjn      return -1;
554f76d27a697a7b0bf3b84490baf60623fc96a23afnjn   }
5550788a3f459aa6ba9c956e471a41df8080fc34c7esewardj   headers_end = headers + len;
556f76d27a697a7b0bf3b84490baf60623fc96a23afnjn
557f76d27a697a7b0bf3b84490baf60623fc96a23afnjn
558f76d27a697a7b0bf3b84490baf60623fc96a23afnjn   // Map some segments into client memory:
559f76d27a697a7b0bf3b84490baf60623fc96a23afnjn   // LC_SEGMENT    (text, data, etc)
560f76d27a697a7b0bf3b84490baf60623fc96a23afnjn   // UNIXSTACK     (stack)
561f76d27a697a7b0bf3b84490baf60623fc96a23afnjn   // LOAD_DYLINKER (dyld)
562f76d27a697a7b0bf3b84490baf60623fc96a23afnjn   lcend = (struct load_command *)(headers + mh.sizeofcmds + sizeof(mh));
563f76d27a697a7b0bf3b84490baf60623fc96a23afnjn   for (lc = (struct load_command *)(headers + sizeof(mh));
564f76d27a697a7b0bf3b84490baf60623fc96a23afnjn        lc < lcend;
565f76d27a697a7b0bf3b84490baf60623fc96a23afnjn        lc = (struct load_command *)(lc->cmdsize + (vki_uint8_t *)lc))
566f76d27a697a7b0bf3b84490baf60623fc96a23afnjn   {
567f76d27a697a7b0bf3b84490baf60623fc96a23afnjn      if ((vki_uint8_t *)lc < headers  ||
568f76d27a697a7b0bf3b84490baf60623fc96a23afnjn          lc->cmdsize+(vki_uint8_t *)lc > headers_end) {
569f76d27a697a7b0bf3b84490baf60623fc96a23afnjn          print("bad executable (invalid load commands)\n");
570f76d27a697a7b0bf3b84490baf60623fc96a23afnjn          return -1;
571f76d27a697a7b0bf3b84490baf60623fc96a23afnjn      }
572f76d27a697a7b0bf3b84490baf60623fc96a23afnjn
573f76d27a697a7b0bf3b84490baf60623fc96a23afnjn      switch (lc->cmd) {
574ae284e5cc0830afcdec7b436564ea9f18bbedff8sewardj
575ec66ad5f33a4d904b1f728935ec6ee29b58a55ecsewardj#if   DARWIN_VERS >= DARWIN_10_8
576ae284e5cc0830afcdec7b436564ea9f18bbedff8sewardj      case LC_MAIN: { /* New in 10.8 */
577ae284e5cc0830afcdec7b436564ea9f18bbedff8sewardj         struct entry_point_command* epcmd
578ae284e5cc0830afcdec7b436564ea9f18bbedff8sewardj            = (struct entry_point_command*)lc;
579ae284e5cc0830afcdec7b436564ea9f18bbedff8sewardj         if (stack_start || stack_end) {
580ae284e5cc0830afcdec7b436564ea9f18bbedff8sewardj            print("bad executable (multiple indications of stack)");
581ae284e5cc0830afcdec7b436564ea9f18bbedff8sewardj            return -1;
582ae284e5cc0830afcdec7b436564ea9f18bbedff8sewardj         }
583ae284e5cc0830afcdec7b436564ea9f18bbedff8sewardj         err = handle_lcmain ( &stack_start, &stack_end, epcmd->stacksize );
584ae284e5cc0830afcdec7b436564ea9f18bbedff8sewardj         if (err) return -1;
585ae284e5cc0830afcdec7b436564ea9f18bbedff8sewardj         VG_(debugLog)(2, "ume", "lc_main: created stack %p-%p\n",
586ae284e5cc0830afcdec7b436564ea9f18bbedff8sewardj	               stack_start, stack_end);
587ae284e5cc0830afcdec7b436564ea9f18bbedff8sewardj         break;
588ae284e5cc0830afcdec7b436564ea9f18bbedff8sewardj      }
589ae284e5cc0830afcdec7b436564ea9f18bbedff8sewardj#     endif
590ae284e5cc0830afcdec7b436564ea9f18bbedff8sewardj
591f76d27a697a7b0bf3b84490baf60623fc96a23afnjn      case LC_SEGMENT_CMD:
592f76d27a697a7b0bf3b84490baf60623fc96a23afnjn         if (lc->cmdsize < sizeof(struct SEGMENT_COMMAND)) {
593f76d27a697a7b0bf3b84490baf60623fc96a23afnjn            print("bad executable (invalid load commands)\n");
594f76d27a697a7b0bf3b84490baf60623fc96a23afnjn            return -1;
595f76d27a697a7b0bf3b84490baf60623fc96a23afnjn         }
596f76d27a697a7b0bf3b84490baf60623fc96a23afnjn         segcmd = (struct SEGMENT_COMMAND *)lc;
597f76d27a697a7b0bf3b84490baf60623fc96a23afnjn         err = load_segment(fd, offset, size, &text, &stack_start,
598f76d27a697a7b0bf3b84490baf60623fc96a23afnjn                            segcmd, filename);
599f76d27a697a7b0bf3b84490baf60623fc96a23afnjn         if (err) return -1;
600f76d27a697a7b0bf3b84490baf60623fc96a23afnjn
601f76d27a697a7b0bf3b84490baf60623fc96a23afnjn         break;
602f76d27a697a7b0bf3b84490baf60623fc96a23afnjn
603f76d27a697a7b0bf3b84490baf60623fc96a23afnjn      case LC_UNIXTHREAD:
604f76d27a697a7b0bf3b84490baf60623fc96a23afnjn         if (stack_end  ||  entry) {
605f76d27a697a7b0bf3b84490baf60623fc96a23afnjn            print("bad executable (multiple thread commands)\n");
606f76d27a697a7b0bf3b84490baf60623fc96a23afnjn            return -1;
607f76d27a697a7b0bf3b84490baf60623fc96a23afnjn         }
608f76d27a697a7b0bf3b84490baf60623fc96a23afnjn         if (lc->cmdsize < sizeof(struct thread_command)) {
609f76d27a697a7b0bf3b84490baf60623fc96a23afnjn            print("bad executable (invalid load commands)\n");
610f76d27a697a7b0bf3b84490baf60623fc96a23afnjn            return -1;
611f76d27a697a7b0bf3b84490baf60623fc96a23afnjn         }
612f76d27a697a7b0bf3b84490baf60623fc96a23afnjn         threadcmd = (struct thread_command *)lc;
613f76d27a697a7b0bf3b84490baf60623fc96a23afnjn         err = load_unixthread(&stack_start, &stack_end, &entry, threadcmd);
614f76d27a697a7b0bf3b84490baf60623fc96a23afnjn         if (err) return -1;
615f76d27a697a7b0bf3b84490baf60623fc96a23afnjn         break;
616f76d27a697a7b0bf3b84490baf60623fc96a23afnjn
617f76d27a697a7b0bf3b84490baf60623fc96a23afnjn      case LC_LOAD_DYLINKER:
618f76d27a697a7b0bf3b84490baf60623fc96a23afnjn         if (filetype == MH_DYLINKER) {
619f76d27a697a7b0bf3b84490baf60623fc96a23afnjn            print("bad executable (dylinker needs a dylinker)\n");
620f76d27a697a7b0bf3b84490baf60623fc96a23afnjn            return -1;
621f76d27a697a7b0bf3b84490baf60623fc96a23afnjn         }
622f76d27a697a7b0bf3b84490baf60623fc96a23afnjn         if (linker_entry) {
623f76d27a697a7b0bf3b84490baf60623fc96a23afnjn            print("bad executable (multiple dylinker commands)\n");
624f76d27a697a7b0bf3b84490baf60623fc96a23afnjn         }
625f76d27a697a7b0bf3b84490baf60623fc96a23afnjn         if (lc->cmdsize < sizeof(struct dylinker_command)) {
626f76d27a697a7b0bf3b84490baf60623fc96a23afnjn            print("bad executable (invalid load commands)\n");
627f76d27a697a7b0bf3b84490baf60623fc96a23afnjn            return -1;
628f76d27a697a7b0bf3b84490baf60623fc96a23afnjn         }
629f76d27a697a7b0bf3b84490baf60623fc96a23afnjn         dycmd = (struct dylinker_command *)lc;
630f76d27a697a7b0bf3b84490baf60623fc96a23afnjn         err = load_dylinker(&linker_entry, dycmd);
631f76d27a697a7b0bf3b84490baf60623fc96a23afnjn         if (err) return -1;
632f76d27a697a7b0bf3b84490baf60623fc96a23afnjn         break;
633f76d27a697a7b0bf3b84490baf60623fc96a23afnjn
634f76d27a697a7b0bf3b84490baf60623fc96a23afnjn      case LC_THREAD:
635f76d27a697a7b0bf3b84490baf60623fc96a23afnjn         if (filetype == MH_EXECUTE) {
636f76d27a697a7b0bf3b84490baf60623fc96a23afnjn            print("bad executable (stackless thread)\n");
637f76d27a697a7b0bf3b84490baf60623fc96a23afnjn            return -1;
638f76d27a697a7b0bf3b84490baf60623fc96a23afnjn         }
639f76d27a697a7b0bf3b84490baf60623fc96a23afnjn         if (stack_end  ||  entry) {
640f76d27a697a7b0bf3b84490baf60623fc96a23afnjn            print("bad executable (multiple thread commands)\n");
641f76d27a697a7b0bf3b84490baf60623fc96a23afnjn            return -1;
642f76d27a697a7b0bf3b84490baf60623fc96a23afnjn         }
643f76d27a697a7b0bf3b84490baf60623fc96a23afnjn         if (lc->cmdsize < sizeof(struct thread_command)) {
644f76d27a697a7b0bf3b84490baf60623fc96a23afnjn            print("bad executable (invalid load commands)\n");
645f76d27a697a7b0bf3b84490baf60623fc96a23afnjn            return -1;
646f76d27a697a7b0bf3b84490baf60623fc96a23afnjn         }
647f76d27a697a7b0bf3b84490baf60623fc96a23afnjn         threadcmd = (struct thread_command *)lc;
648f76d27a697a7b0bf3b84490baf60623fc96a23afnjn         err = load_thread(&entry, threadcmd);
649f76d27a697a7b0bf3b84490baf60623fc96a23afnjn         if (err) return -1;
650f76d27a697a7b0bf3b84490baf60623fc96a23afnjn         break;
651f76d27a697a7b0bf3b84490baf60623fc96a23afnjn
652f76d27a697a7b0bf3b84490baf60623fc96a23afnjn      default:
653f76d27a697a7b0bf3b84490baf60623fc96a23afnjn         break;
654f76d27a697a7b0bf3b84490baf60623fc96a23afnjn      }
655f76d27a697a7b0bf3b84490baf60623fc96a23afnjn   }
656f76d27a697a7b0bf3b84490baf60623fc96a23afnjn
657f76d27a697a7b0bf3b84490baf60623fc96a23afnjn
658f76d27a697a7b0bf3b84490baf60623fc96a23afnjn   // Done with the headers
659f76d27a697a7b0bf3b84490baf60623fc96a23afnjn   VG_(free)(headers);
660f76d27a697a7b0bf3b84490baf60623fc96a23afnjn
661f76d27a697a7b0bf3b84490baf60623fc96a23afnjn   if (filetype == MH_EXECUTE) {
662f76d27a697a7b0bf3b84490baf60623fc96a23afnjn      // Verify the necessary pieces for an executable:
663f76d27a697a7b0bf3b84490baf60623fc96a23afnjn      // a stack
664f76d27a697a7b0bf3b84490baf60623fc96a23afnjn      // a text segment
665f76d27a697a7b0bf3b84490baf60623fc96a23afnjn      // an entry point (static or linker)
666f76d27a697a7b0bf3b84490baf60623fc96a23afnjn      if (!stack_end || !stack_start) {
667ae284e5cc0830afcdec7b436564ea9f18bbedff8sewardj         VG_(printf)("bad executable %s (no stack)\n", filename);
668f76d27a697a7b0bf3b84490baf60623fc96a23afnjn         return -1;
669f76d27a697a7b0bf3b84490baf60623fc96a23afnjn      }
670f76d27a697a7b0bf3b84490baf60623fc96a23afnjn      if (!text) {
671f76d27a697a7b0bf3b84490baf60623fc96a23afnjn         print("bad executable (no text segment)\n");
672f76d27a697a7b0bf3b84490baf60623fc96a23afnjn         return -1;
673f76d27a697a7b0bf3b84490baf60623fc96a23afnjn      }
674f76d27a697a7b0bf3b84490baf60623fc96a23afnjn      if (!entry  &&  !linker_entry) {
675f76d27a697a7b0bf3b84490baf60623fc96a23afnjn         print("bad executable (no entry point)\n");
676f76d27a697a7b0bf3b84490baf60623fc96a23afnjn         return -1;
677f76d27a697a7b0bf3b84490baf60623fc96a23afnjn      }
678f76d27a697a7b0bf3b84490baf60623fc96a23afnjn   }
679f76d27a697a7b0bf3b84490baf60623fc96a23afnjn   else if (filetype == MH_DYLINKER) {
680f76d27a697a7b0bf3b84490baf60623fc96a23afnjn      // Verify the necessary pieces for a dylinker:
681f76d27a697a7b0bf3b84490baf60623fc96a23afnjn      // an entry point
682f76d27a697a7b0bf3b84490baf60623fc96a23afnjn      if (!entry) {
683f76d27a697a7b0bf3b84490baf60623fc96a23afnjn         print("bad executable (no entry point)\n");
684f76d27a697a7b0bf3b84490baf60623fc96a23afnjn         return -1;
685f76d27a697a7b0bf3b84490baf60623fc96a23afnjn      }
686f76d27a697a7b0bf3b84490baf60623fc96a23afnjn   }
687f76d27a697a7b0bf3b84490baf60623fc96a23afnjn
688f76d27a697a7b0bf3b84490baf60623fc96a23afnjn   if (out_stack_start) *out_stack_start = stack_start;
689f76d27a697a7b0bf3b84490baf60623fc96a23afnjn   if (out_stack_end) *out_stack_end = stack_end;
690f76d27a697a7b0bf3b84490baf60623fc96a23afnjn   if (out_text)  *out_text = text;
691f76d27a697a7b0bf3b84490baf60623fc96a23afnjn   if (out_entry) *out_entry = entry;
692f76d27a697a7b0bf3b84490baf60623fc96a23afnjn   if (out_linker_entry) *out_linker_entry = linker_entry;
693f76d27a697a7b0bf3b84490baf60623fc96a23afnjn
694ae284e5cc0830afcdec7b436564ea9f18bbedff8sewardj   VG_(debugLog)(1, "ume", "load_thin_file: success: %s\n", filename);
695f76d27a697a7b0bf3b84490baf60623fc96a23afnjn   return 0;
696f76d27a697a7b0bf3b84490baf60623fc96a23afnjn}
697f76d27a697a7b0bf3b84490baf60623fc96a23afnjn
698f76d27a697a7b0bf3b84490baf60623fc96a23afnjn
699f76d27a697a7b0bf3b84490baf60623fc96a23afnjn/*
700f76d27a697a7b0bf3b84490baf60623fc96a23afnjn Load a fat Mach-O executable.
701f76d27a697a7b0bf3b84490baf60623fc96a23afnjn*/
702f76d27a697a7b0bf3b84490baf60623fc96a23afnjnstatic int
703f76d27a697a7b0bf3b84490baf60623fc96a23afnjnload_fat_file(int fd, vki_off_t offset, vki_off_t size, unsigned long filetype,
7040af78adc02d94916ae0d31ffc02e40e3bea11877florian             const HChar *filename,
705f76d27a697a7b0bf3b84490baf60623fc96a23afnjn             vki_uint8_t **out_stack_start, vki_uint8_t **out_stack_end,
706f76d27a697a7b0bf3b84490baf60623fc96a23afnjn             vki_uint8_t **out_text, vki_uint8_t **out_entry, vki_uint8_t **out_linker_entry)
707f76d27a697a7b0bf3b84490baf60623fc96a23afnjn{
708f76d27a697a7b0bf3b84490baf60623fc96a23afnjn   struct fat_header fh;
709f76d27a697a7b0bf3b84490baf60623fc96a23afnjn   vki_off_t arch_offset;
710f76d27a697a7b0bf3b84490baf60623fc96a23afnjn   int i;
711f76d27a697a7b0bf3b84490baf60623fc96a23afnjn   cpu_type_t good_arch;
712f76d27a697a7b0bf3b84490baf60623fc96a23afnjn   SysRes res;
713f76d27a697a7b0bf3b84490baf60623fc96a23afnjn
714f76d27a697a7b0bf3b84490baf60623fc96a23afnjn#if defined(VGA_ppc32)
715f76d27a697a7b0bf3b84490baf60623fc96a23afnjn   good_arch = CPU_TYPE_POWERPC;
716cae0cc22b83ffb260ee8379e92099c5a701944cbcarll#elif defined(VGA_ppc64be)
717cae0cc22b83ffb260ee8379e92099c5a701944cbcarll   good_arch = CPU_TYPE_POWERPC64BE;
718582d58245637ab05272d89fb94b12fd0f18fa0f8carll#elif defined(VGA_ppc64le)
719582d58245637ab05272d89fb94b12fd0f18fa0f8carll   good_arch = CPU_TYPE_POWERPC64LE;
720f76d27a697a7b0bf3b84490baf60623fc96a23afnjn#elif defined(VGA_x86)
721f76d27a697a7b0bf3b84490baf60623fc96a23afnjn   good_arch = CPU_TYPE_I386;
722f76d27a697a7b0bf3b84490baf60623fc96a23afnjn#elif defined(VGA_amd64)
723f76d27a697a7b0bf3b84490baf60623fc96a23afnjn   good_arch = CPU_TYPE_X86_64;
724f76d27a697a7b0bf3b84490baf60623fc96a23afnjn#else
725f76d27a697a7b0bf3b84490baf60623fc96a23afnjn# error unknown architecture
726f76d27a697a7b0bf3b84490baf60623fc96a23afnjn#endif
727f76d27a697a7b0bf3b84490baf60623fc96a23afnjn
728f76d27a697a7b0bf3b84490baf60623fc96a23afnjn   // Read fat header
729f76d27a697a7b0bf3b84490baf60623fc96a23afnjn   // All fat contents are BIG-ENDIAN
730f76d27a697a7b0bf3b84490baf60623fc96a23afnjn   if (size < sizeof(fh)) {
731f76d27a697a7b0bf3b84490baf60623fc96a23afnjn      print("bad executable (bad fat header)\n");
732f76d27a697a7b0bf3b84490baf60623fc96a23afnjn      return -1;
733f76d27a697a7b0bf3b84490baf60623fc96a23afnjn   }
734f76d27a697a7b0bf3b84490baf60623fc96a23afnjn   res = VG_(pread)(fd, &fh, sizeof(fh), offset);
735f76d27a697a7b0bf3b84490baf60623fc96a23afnjn   if (sr_isError(res)  ||  sr_Res(res) != sizeof(fh)) {
736f76d27a697a7b0bf3b84490baf60623fc96a23afnjn      print("bad executable (bad fat header)\n");
737f76d27a697a7b0bf3b84490baf60623fc96a23afnjn      return -1;
738f76d27a697a7b0bf3b84490baf60623fc96a23afnjn   }
739f76d27a697a7b0bf3b84490baf60623fc96a23afnjn
740f76d27a697a7b0bf3b84490baf60623fc96a23afnjn   // Scan arch headers looking for a good one
741f76d27a697a7b0bf3b84490baf60623fc96a23afnjn   arch_offset = offset + sizeof(fh);
742f76d27a697a7b0bf3b84490baf60623fc96a23afnjn   fh.nfat_arch = VG_(ntohl)(fh.nfat_arch);
743f76d27a697a7b0bf3b84490baf60623fc96a23afnjn   for (i = 0; i < fh.nfat_arch; i++) {
744f76d27a697a7b0bf3b84490baf60623fc96a23afnjn      struct fat_arch arch;
745f76d27a697a7b0bf3b84490baf60623fc96a23afnjn      if (arch_offset + sizeof(arch) > size) {
746f76d27a697a7b0bf3b84490baf60623fc96a23afnjn          print("bad executable (corrupt fat archs)\n");
747f76d27a697a7b0bf3b84490baf60623fc96a23afnjn          return -1;
748f76d27a697a7b0bf3b84490baf60623fc96a23afnjn      }
749f76d27a697a7b0bf3b84490baf60623fc96a23afnjn
750f76d27a697a7b0bf3b84490baf60623fc96a23afnjn      res = VG_(pread)(fd, &arch, sizeof(arch), arch_offset);
751f76d27a697a7b0bf3b84490baf60623fc96a23afnjn      arch_offset += sizeof(arch);
752f76d27a697a7b0bf3b84490baf60623fc96a23afnjn      if (sr_isError(res)  ||  sr_Res(res) != sizeof(arch)) {
753f76d27a697a7b0bf3b84490baf60623fc96a23afnjn         VG_(printf)("bad executable (corrupt fat arch) %x %llu\n",
754f76d27a697a7b0bf3b84490baf60623fc96a23afnjn                     arch.cputype, (ULong)arch_offset);
755f76d27a697a7b0bf3b84490baf60623fc96a23afnjn         return -1;
756f76d27a697a7b0bf3b84490baf60623fc96a23afnjn      }
757f76d27a697a7b0bf3b84490baf60623fc96a23afnjn
758f76d27a697a7b0bf3b84490baf60623fc96a23afnjn      arch.cputype = VG_(ntohl)(arch.cputype);
759f76d27a697a7b0bf3b84490baf60623fc96a23afnjn      arch.cpusubtype = VG_(ntohl)(arch.cpusubtype);
760f76d27a697a7b0bf3b84490baf60623fc96a23afnjn      arch.offset = VG_(ntohl)(arch.offset);
761f76d27a697a7b0bf3b84490baf60623fc96a23afnjn      arch.size = VG_(ntohl)(arch.size);
762f76d27a697a7b0bf3b84490baf60623fc96a23afnjn      arch.align = VG_(ntohl)(arch.align);
763f76d27a697a7b0bf3b84490baf60623fc96a23afnjn      if (arch.cputype == good_arch) {
764f76d27a697a7b0bf3b84490baf60623fc96a23afnjn         // use this arch
765f76d27a697a7b0bf3b84490baf60623fc96a23afnjn         if (arch.offset > size  ||  arch.offset + arch.size > size) {
766f76d27a697a7b0bf3b84490baf60623fc96a23afnjn            print("bad executable (corrupt fat arch 2)\n");
767f76d27a697a7b0bf3b84490baf60623fc96a23afnjn            return -1;
768f76d27a697a7b0bf3b84490baf60623fc96a23afnjn         }
769f76d27a697a7b0bf3b84490baf60623fc96a23afnjn         return load_mach_file(fd, offset+arch.offset, arch.size, filetype,
770f76d27a697a7b0bf3b84490baf60623fc96a23afnjn                               filename, out_stack_start, out_stack_end,
771f76d27a697a7b0bf3b84490baf60623fc96a23afnjn                               out_text, out_entry, out_linker_entry);
772f76d27a697a7b0bf3b84490baf60623fc96a23afnjn      }
773f76d27a697a7b0bf3b84490baf60623fc96a23afnjn   }
774f76d27a697a7b0bf3b84490baf60623fc96a23afnjn
775f76d27a697a7b0bf3b84490baf60623fc96a23afnjn   print("bad executable (can't run on this machine)\n");
776f76d27a697a7b0bf3b84490baf60623fc96a23afnjn   return -1;
777f76d27a697a7b0bf3b84490baf60623fc96a23afnjn}
778f76d27a697a7b0bf3b84490baf60623fc96a23afnjn
779f76d27a697a7b0bf3b84490baf60623fc96a23afnjn/*
780f76d27a697a7b0bf3b84490baf60623fc96a23afnjn Load a Mach-O executable or dylinker.
781f76d27a697a7b0bf3b84490baf60623fc96a23afnjn The file may be fat or thin.
782f76d27a697a7b0bf3b84490baf60623fc96a23afnjn*/
783f76d27a697a7b0bf3b84490baf60623fc96a23afnjnstatic int
784f76d27a697a7b0bf3b84490baf60623fc96a23afnjnload_mach_file(int fd, vki_off_t offset, vki_off_t size, unsigned long filetype,
7850af78adc02d94916ae0d31ffc02e40e3bea11877florian              const HChar *filename,
786f76d27a697a7b0bf3b84490baf60623fc96a23afnjn              vki_uint8_t **out_stack_start, vki_uint8_t **out_stack_end,
787f76d27a697a7b0bf3b84490baf60623fc96a23afnjn              vki_uint8_t **out_text, vki_uint8_t **out_entry, vki_uint8_t **out_linker_entry)
788f76d27a697a7b0bf3b84490baf60623fc96a23afnjn{
789f76d27a697a7b0bf3b84490baf60623fc96a23afnjn   vki_uint32_t magic;
790f76d27a697a7b0bf3b84490baf60623fc96a23afnjn   SysRes res;
791f76d27a697a7b0bf3b84490baf60623fc96a23afnjn
792f76d27a697a7b0bf3b84490baf60623fc96a23afnjn   if (size < sizeof(magic)) {
793f76d27a697a7b0bf3b84490baf60623fc96a23afnjn      print("bad executable (no Mach-O magic)\n");
794f76d27a697a7b0bf3b84490baf60623fc96a23afnjn      return -1;
795f76d27a697a7b0bf3b84490baf60623fc96a23afnjn   }
796f76d27a697a7b0bf3b84490baf60623fc96a23afnjn   res = VG_(pread)(fd, &magic, sizeof(magic), offset);
797f76d27a697a7b0bf3b84490baf60623fc96a23afnjn   if (sr_isError(res)  ||  sr_Res(res) != sizeof(magic)) {
798f76d27a697a7b0bf3b84490baf60623fc96a23afnjn      print("bad executable (no Mach-O magic)\n");
799f76d27a697a7b0bf3b84490baf60623fc96a23afnjn      return -1;
800f76d27a697a7b0bf3b84490baf60623fc96a23afnjn   }
801f76d27a697a7b0bf3b84490baf60623fc96a23afnjn
802f76d27a697a7b0bf3b84490baf60623fc96a23afnjn   if (magic == MAGIC) {
803f76d27a697a7b0bf3b84490baf60623fc96a23afnjn      // thin
804f76d27a697a7b0bf3b84490baf60623fc96a23afnjn      return load_thin_file(fd, offset, size, filetype, filename,
805f76d27a697a7b0bf3b84490baf60623fc96a23afnjn                            out_stack_start, out_stack_end,
806f76d27a697a7b0bf3b84490baf60623fc96a23afnjn                            out_text, out_entry, out_linker_entry);
807f76d27a697a7b0bf3b84490baf60623fc96a23afnjn   } else if (magic == VG_(htonl)(FAT_MAGIC)) {
808f76d27a697a7b0bf3b84490baf60623fc96a23afnjn      // fat
809f76d27a697a7b0bf3b84490baf60623fc96a23afnjn      return load_fat_file(fd, offset, size, filetype, filename,
810f76d27a697a7b0bf3b84490baf60623fc96a23afnjn                           out_stack_start, out_stack_end,
811f76d27a697a7b0bf3b84490baf60623fc96a23afnjn                           out_text, out_entry, out_linker_entry);
812f76d27a697a7b0bf3b84490baf60623fc96a23afnjn   } else {
813f76d27a697a7b0bf3b84490baf60623fc96a23afnjn      // huh?
814f76d27a697a7b0bf3b84490baf60623fc96a23afnjn      print("bad executable (bad Mach-O magic)\n");
815f76d27a697a7b0bf3b84490baf60623fc96a23afnjn      return -1;
816f76d27a697a7b0bf3b84490baf60623fc96a23afnjn   }
817f76d27a697a7b0bf3b84490baf60623fc96a23afnjn}
818f76d27a697a7b0bf3b84490baf60623fc96a23afnjn
819f76d27a697a7b0bf3b84490baf60623fc96a23afnjn
820ff4a0841ea935fdbd7dae4561073eb9501cc9491florianBool VG_(match_macho)(const void *hdr, SizeT len)
821f76d27a697a7b0bf3b84490baf60623fc96a23afnjn{
8220af78adc02d94916ae0d31ffc02e40e3bea11877florian   const vki_uint32_t *magic = hdr;
823f76d27a697a7b0bf3b84490baf60623fc96a23afnjn
824f76d27a697a7b0bf3b84490baf60623fc96a23afnjn   // GrP fixme check more carefully for matching fat arch?
825f76d27a697a7b0bf3b84490baf60623fc96a23afnjn
826f76d27a697a7b0bf3b84490baf60623fc96a23afnjn   return (len >= VKI_PAGE_SIZE  &&
827f76d27a697a7b0bf3b84490baf60623fc96a23afnjn           (*magic == MAGIC  ||  *magic == VG_(ntohl)(FAT_MAGIC)))
828f76d27a697a7b0bf3b84490baf60623fc96a23afnjn      ? True : False;
829f76d27a697a7b0bf3b84490baf60623fc96a23afnjn}
830f76d27a697a7b0bf3b84490baf60623fc96a23afnjn
831f76d27a697a7b0bf3b84490baf60623fc96a23afnjn
832f76d27a697a7b0bf3b84490baf60623fc96a23afnjnInt VG_(load_macho)(Int fd, const HChar *name, ExeInfo *info)
833f76d27a697a7b0bf3b84490baf60623fc96a23afnjn{
834f76d27a697a7b0bf3b84490baf60623fc96a23afnjn   int err;
835f76d27a697a7b0bf3b84490baf60623fc96a23afnjn   struct vg_stat sb;
836f76d27a697a7b0bf3b84490baf60623fc96a23afnjn   vki_uint8_t *stack_start;
837f76d27a697a7b0bf3b84490baf60623fc96a23afnjn   vki_uint8_t *stack_end;
838f76d27a697a7b0bf3b84490baf60623fc96a23afnjn   vki_uint8_t *text;
839f76d27a697a7b0bf3b84490baf60623fc96a23afnjn   vki_uint8_t *entry;
840f76d27a697a7b0bf3b84490baf60623fc96a23afnjn   vki_uint8_t *linker_entry;
841f76d27a697a7b0bf3b84490baf60623fc96a23afnjn
842f76d27a697a7b0bf3b84490baf60623fc96a23afnjn   err = VG_(fstat)(fd, &sb);
843f76d27a697a7b0bf3b84490baf60623fc96a23afnjn   if (err) {
844f76d27a697a7b0bf3b84490baf60623fc96a23afnjn      print("couldn't stat executable\n");
845f76d27a697a7b0bf3b84490baf60623fc96a23afnjn      return VKI_ENOEXEC;
846f76d27a697a7b0bf3b84490baf60623fc96a23afnjn   }
847f76d27a697a7b0bf3b84490baf60623fc96a23afnjn
848f76d27a697a7b0bf3b84490baf60623fc96a23afnjn   err = load_mach_file(fd, 0, sb.size, MH_EXECUTE, name,
849f76d27a697a7b0bf3b84490baf60623fc96a23afnjn                        &stack_start, &stack_end,
850f76d27a697a7b0bf3b84490baf60623fc96a23afnjn                        &text, &entry, &linker_entry);
851f76d27a697a7b0bf3b84490baf60623fc96a23afnjn   if (err) return VKI_ENOEXEC;
852f76d27a697a7b0bf3b84490baf60623fc96a23afnjn
853f76d27a697a7b0bf3b84490baf60623fc96a23afnjn   // GrP fixme exe_base
854f76d27a697a7b0bf3b84490baf60623fc96a23afnjn   // GrP fixme exe_end
855f76d27a697a7b0bf3b84490baf60623fc96a23afnjn   info->entry = (Addr)entry;
856f76d27a697a7b0bf3b84490baf60623fc96a23afnjn   info->init_ip = (Addr)(linker_entry ? linker_entry : entry);
857f76d27a697a7b0bf3b84490baf60623fc96a23afnjn   info->brkbase = 0xffffffff; // GrP fixme hack
858f76d27a697a7b0bf3b84490baf60623fc96a23afnjn   info->init_toc = 0; // GrP fixme unused
859f76d27a697a7b0bf3b84490baf60623fc96a23afnjn
860f76d27a697a7b0bf3b84490baf60623fc96a23afnjn   info->stack_start = (Addr)stack_start;
861f76d27a697a7b0bf3b84490baf60623fc96a23afnjn   info->stack_end = (Addr)stack_end;
862f76d27a697a7b0bf3b84490baf60623fc96a23afnjn   info->text = (Addr)text;
863f76d27a697a7b0bf3b84490baf60623fc96a23afnjn   info->dynamic = linker_entry ? True : False;
864f76d27a697a7b0bf3b84490baf60623fc96a23afnjn
865f76d27a697a7b0bf3b84490baf60623fc96a23afnjn   info->executable_path = VG_(strdup)("ume.macho.executable_path", name);
866f76d27a697a7b0bf3b84490baf60623fc96a23afnjn
867f76d27a697a7b0bf3b84490baf60623fc96a23afnjn   return 0;
868f76d27a697a7b0bf3b84490baf60623fc96a23afnjn}
869f76d27a697a7b0bf3b84490baf60623fc96a23afnjn
8708b68b64759254d514d98328c496cbd88cde4c9a5njn#endif // defined(VGO_darwin)
871f76d27a697a7b0bf3b84490baf60623fc96a23afnjn
872f76d27a697a7b0bf3b84490baf60623fc96a23afnjn/*--------------------------------------------------------------------*/
873f76d27a697a7b0bf3b84490baf60623fc96a23afnjn/*--- end                                                          ---*/
874f76d27a697a7b0bf3b84490baf60623fc96a23afnjn/*--------------------------------------------------------------------*/
875f76d27a697a7b0bf3b84490baf60623fc96a23afnjn
876