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