2 /*--------------------------------------------------------------------*/
3 /*--- User-mode execve() for Mach-O executables m_ume_macho.c ---*/
4 /*--------------------------------------------------------------------*/
7 This file is part of Valgrind, a dynamic binary instrumentation
10 Copyright (C) 2005-2017 Apple Inc.
11 Greg Parker gparker@apple.com
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.
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.
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
28 The GNU General Public License is contained in the file COPYING.
31 #if defined(VGO_darwin)
33 #include "pub_core_basics.h"
34 #include "pub_core_vki.h"
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
50 #include <mach/mach.h>
52 #include <mach-o/dyld.h>
53 #include <mach-o/fat.h>
54 #include <mach-o/loader.h>
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
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
70 typedef struct load_info_t
{
71 vki_uint8_t
*stack_start
; // allocated thread stack (hot end)
72 vki_uint8_t
*stack_end
; // allocated thread stack (cold end)
73 vki_uint8_t
*text
; // start of text segment (i.e. the mach headers)
74 vki_uint8_t
*entry
; // static entry point
75 vki_uint8_t
*linker_entry
; // dylinker entry point
76 Addr linker_offset
; // dylinker text offset
77 vki_size_t max_addr
; // biggest address reached while loading segments
80 static void print(const HChar
*str
)
82 VG_(printf
)("%s", str
);
85 static void check_mmap(SysRes res
, Addr base
, SizeT len
, const HChar
* who
)
87 if (sr_isError(res
)) {
88 VG_(printf
)("valgrind: mmap-FIXED(0x%llx, %lld) failed in UME (%s) "
89 "with error %lu (%s).\n",
90 (ULong
)base
, (Long
)len
, who
,
91 sr_Err(res
), VG_(strerror
)(sr_Err(res
)) );
96 #if DARWIN_VERS >= DARWIN_10_8
97 static void check_mmap_float(SysRes res
, SizeT len
, const HChar
* who
)
99 if (sr_isError(res
)) {
100 VG_(printf
)("valgrind: mmap-FLOAT(size=%lld) failed in UME (%s) "
101 "with error %lu (%s).\n",
103 sr_Err(res
), VG_(strerror
)(sr_Err(res
)) );
110 load_thin_file(int fd
, vki_off_t offset
, vki_off_t size
, unsigned long filetype
,
111 const HChar
*filename
, load_info_t
*out_info
);
114 load_fat_file(int fd
, vki_off_t offset
, vki_off_t size
, unsigned long filetype
,
115 const HChar
*filename
, load_info_t
*out_info
);
118 load_mach_file(int fd
, vki_off_t offset
, vki_off_t size
, unsigned long filetype
,
119 const HChar
*filename
, load_info_t
*out_info
);
122 /* Open and map a dylinker file.
123 Returns 0 on success, -1 on any failure.
124 filename must be an absolute path.
125 The dylinker's entry point is returned in out_info->linker_entry.
128 open_dylinker(const HChar
*filename
, load_info_t
*out_info
)
136 if (filename
[0] != '/') {
137 print("bad executable (dylinker name is not an absolute path)\n");
141 res
= VG_(open
)(filename
, VKI_O_RDONLY
, 0);
143 if (sr_isError(res
)) {
144 VG_(printf
)("couldn't open dylinker: %s\n", filename
);
147 err
= VG_(fstat
)(fd
, &sb
);
149 VG_(printf
)("couldn't stat dylinker: %s\n", filename
);
155 err
= load_mach_file(fd
, 0, filesize
, MH_DYLINKER
, filename
, out_info
);
157 VG_(printf
)("...while loading dylinker: %s\n", filename
);
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 out_info->text.
170 If this segment is a __UNIXSTACK, its start address is returned in
171 out_info->stack_start.
174 load_segment(int fd
, vki_off_t offset
, vki_off_t size
,
175 struct SEGMENT_COMMAND
*segcmd
, const HChar
*filename
,
176 load_info_t
*out_info
)
180 vki_size_t filesize
; // page-aligned
181 vki_size_t vmsize
; // page-aligned
182 vki_size_t vmend
; // page-aligned
184 Addr slided_addr
= segcmd
->vmaddr
+ out_info
->linker_offset
;
186 // GrP fixme mark __UNIXSTACK as SF_STACK
188 // Don't honour the client's request to map PAGEZERO. Why not?
189 // Because when the kernel loaded the valgrind tool executable,
190 // it will have mapped pagezero itself. So further attempts
191 // to map it when loading the client are guaranteed to fail.
193 if (segcmd
->vmaddr
== 0 && 0 == VG_(strcmp
)(segcmd
->segname
, SEG_PAGEZERO
)) {
194 if (segcmd
->vmsize
!= 0x1000) {
195 print("bad executable (__PAGEZERO is not 4 KB)\n");
202 if (segcmd
->vmaddr
== 0 && 0 == VG_(strcmp
)(segcmd
->segname
, SEG_PAGEZERO
)) {
203 if (segcmd
->vmsize
!= 0x100000000) {
204 print("bad executable (__PAGEZERO is not 4 GB)\n");
211 // Record the segment containing the Mach headers themselves
212 if (segcmd
->fileoff
== 0 && segcmd
->filesize
!= 0) {
213 out_info
->text
= (vki_uint8_t
*)slided_addr
;
216 // Record the __UNIXSTACK start
217 if (0 == VG_(strcmp
)(segcmd
->segname
, SEG_UNIXSTACK
)) {
218 out_info
->stack_start
= (vki_uint8_t
*)slided_addr
;
221 // Sanity-check the segment
222 if (segcmd
->fileoff
+ segcmd
->filesize
> size
) {
223 print("bad executable (invalid segment command)\n");
227 vmend
= VG_PGROUNDUP(slided_addr
+ segcmd
->vmsize
);
228 if (vmend
> out_info
->max_addr
) {
229 out_info
->max_addr
= vmend
;
232 if (segcmd
->vmsize
== 0) {
233 return 0; // nothing to map - ok
236 // Get desired memory protection
237 // GrP fixme need maxprot too
238 prot
= (((segcmd
->initprot
& VM_PROT_READ
) ? VKI_PROT_READ
: 0) |
239 ((segcmd
->initprot
& VM_PROT_WRITE
) ? VKI_PROT_WRITE
: 0) |
240 ((segcmd
->initprot
& VM_PROT_EXECUTE
) ? VKI_PROT_EXEC
: 0));
243 filesize
= VG_PGROUNDUP(segcmd
->filesize
);
244 vmsize
= VG_PGROUNDUP(segcmd
->vmsize
);
247 VG_(debugLog
)(2, "ume", "mmap fixed (file) (%#lx, %lu)\n", addr
, filesize
);
248 res
= VG_(am_mmap_named_file_fixed_client
)(addr
, filesize
, prot
, fd
,
249 offset
+ segcmd
->fileoff
,
251 check_mmap(res
, addr
, filesize
, "load_segment1");
254 // Zero-fill the remainder of the segment, if any
255 if (segcmd
->filesize
!= filesize
) {
256 // non-page-aligned part
257 // GrP fixme kernel doesn't do this?
258 //bzero(segcmd->filesize+(vki_uint8_t *)addr, filesize-segcmd->filesize);
260 if (filesize
!= vmsize
) {
262 SizeT length
= vmsize
- filesize
;
263 addr
= (Addr
)(filesize
+ slided_addr
);
264 VG_(debugLog
)(2, "ume", "mmap fixed (anon) (%#lx, %lu)\n", addr
, length
);
265 res
= VG_(am_mmap_anon_fixed_client
)(addr
, length
, prot
);
266 check_mmap(res
, addr
, length
, "load_segment2");
274 Parse a LC_THREAD or LC_UNIXTHREAD command.
275 Return 0 on success, -1 on any failure.
276 If the thread is a LC_UNIXTHREAD, the stack address is returned in out_info->stack_end.
277 If the executable requested a non-default stack address,
278 *customstack is set to TRUE. The thread's entry point is returned in out_info->entry.
279 The stack itself (if any) is not mapped.
280 Other custom register settings are silently ignored (GrP fixme).
283 load_genericthread(struct thread_command
*threadcmd
, int type
,
284 int *customstack
, load_info_t
*out_info
)
291 p
= (unsigned int *)(threadcmd
+ 1);
292 left
= (threadcmd
->cmdsize
- sizeof(struct thread_command
)) / sizeof(*p
);
296 print("bad executable (invalid thread command)\n");
299 flavor
= *p
++; left
--;
300 count
= *p
++; left
--;
303 print("bad executable (invalid thread command 2)\n");
308 if (flavor
== i386_THREAD_STATE
&& count
== i386_THREAD_STATE_COUNT
) {
309 i386_thread_state_t
*state
= (i386_thread_state_t
*)p
;
310 out_info
->entry
= (vki_uint8_t
*)state
->__eip
;
311 if (type
== LC_UNIXTHREAD
) {
312 out_info
->stack_end
=
313 (vki_uint8_t
*)(state
->__esp
? state
->__esp
: VKI_USRSTACK
);
314 vg_assert(VG_IS_PAGE_ALIGNED(out_info
->stack_end
));
315 out_info
->stack_end
--;
317 if (customstack
) *customstack
= state
->__esp
;
321 #elif defined(VGA_amd64)
322 if (flavor
== x86_THREAD_STATE64
&& count
== x86_THREAD_STATE64_COUNT
){
323 x86_thread_state64_t
*state
= (x86_thread_state64_t
*)p
;
324 out_info
->entry
= (vki_uint8_t
*)state
->__rip
;
325 if (type
== LC_UNIXTHREAD
) {
326 out_info
->stack_end
=
327 (vki_uint8_t
*)(state
->__rsp
? state
->__rsp
: VKI_USRSTACK64
);
328 vg_assert(VG_IS_PAGE_ALIGNED(out_info
->stack_end
));
329 out_info
->stack_end
--;
331 if (customstack
) *customstack
= state
->__rsp
;
336 # error unknown platform
342 print("bad executable (no arch-compatible thread state)\n");
347 /* Returns the main stack size on this platform,
348 using getrlimit or a fixed size.
350 static vki_size_t
default_stack_size(void)
352 struct vki_rlimit lim
;
353 int err
= VG_(getrlimit
)(VKI_RLIMIT_STACK
, &lim
);
354 if (err
) return 8*1024*1024; // 8 MB
355 else return lim
.rlim_cur
;
360 Processes a LC_UNIXTHREAD command.
361 Returns 0 on success, -1 on any failure.
362 The stack is mapped in and returned in out_info->stack_start and out_info->stack_end.
363 The thread's entry point is returned in out_info->entry.
366 load_unixthread(struct thread_command
*threadcmd
, load_info_t
*out_info
)
371 err
= load_genericthread(threadcmd
, LC_UNIXTHREAD
, &customstack
, out_info
);
374 if (!out_info
->stack_end
) {
375 print("bad executable (no thread stack)\n");
381 vki_size_t stacksize
= VG_PGROUNDUP(default_stack_size());
382 vm_address_t stackbase
= VG_PGROUNDDN(out_info
->stack_end
+1-stacksize
);
385 res
= VG_(am_mmap_anon_fixed_client
)(stackbase
, stacksize
, VKI_PROT_READ
|VKI_PROT_WRITE
|VKI_PROT_EXEC
);
386 check_mmap(res
, stackbase
, stacksize
, "load_unixthread1");
387 out_info
->stack_start
= (vki_uint8_t
*)stackbase
;
389 // custom stack - mapped via __UNIXTHREAD segment
396 /* Allocates a stack mapping at a V-chosen address. Pertains to
397 LC_MAIN commands, which seem to have appeared in OSX 10.8.
399 This is a really nasty hack -- allocates 64M+stack size, then
400 deallocates the 64M, to guarantee that the stack is at least 64M
402 #if DARWIN_VERS >= DARWIN_10_8
404 handle_lcmain ( vki_size_t requested_size
,
405 load_info_t
*out_info
)
407 if (requested_size
== 0) {
408 requested_size
= default_stack_size();
410 requested_size
= VG_PGROUNDUP(requested_size
);
412 const vki_size_t HACK
= 64 * 1024 * 1024;
413 requested_size
+= HACK
;
415 SysRes res
= VG_(am_mmap_anon_float_client
)(requested_size
,
416 VKI_PROT_READ
|VKI_PROT_WRITE
|VKI_PROT_EXEC
);
417 check_mmap_float(res
, requested_size
, "handle_lcmain");
418 vg_assert(!sr_isError(res
));
419 out_info
->stack_start
= (vki_uint8_t
*)sr_Res(res
);
420 out_info
->stack_end
= out_info
->stack_start
+ requested_size
- 1;
422 Bool need_discard
= False
;
423 res
= VG_(am_munmap_client
)(&need_discard
, (Addr
)out_info
->stack_start
, HACK
);
424 if (sr_isError(res
)) return -1;
425 vg_assert(!need_discard
); // True == wtf?
427 out_info
->stack_start
+= HACK
;
431 #endif /* DARWIN_VERS >= DARWIN_10_8 */
436 Processes an LC_LOAD_DYLINKER command.
437 Returns 0 on success, -1 on any error.
438 The linker itself is mapped into memory.
439 The linker's entry point is returned in out_info->linker_entry.
442 load_dylinker(struct dylinker_command
*dycmd
, load_info_t
*out_info
)
446 load_info_t linker_info
;
447 linker_info
.stack_start
= NULL
;
448 linker_info
.stack_end
= NULL
;
449 linker_info
.text
= NULL
;
450 linker_info
.entry
= NULL
;
451 linker_info
.linker_entry
= NULL
;
452 linker_info
.linker_offset
= 0;
453 linker_info
.max_addr
= out_info
->max_addr
;
455 if (dycmd
->name
.offset
>= dycmd
->cmdsize
) {
456 print("bad executable (invalid dylinker command)\n");
460 name
= dycmd
->name
.offset
+ (HChar
*)dycmd
;
462 // GrP fixme assumes name is terminated somewhere
463 ret
= open_dylinker(name
, &linker_info
);
464 if (linker_info
.entry
) {
465 out_info
->linker_entry
= linker_info
.entry
+ linker_info
.linker_offset
;
467 out_info
->max_addr
= linker_info
.max_addr
;
473 Process an LC_THREAD command.
474 Returns 0 on success, -1 on any failure.
475 The thread's entry point is returned in out_info->entry.
478 load_thread(struct thread_command
*threadcmd
, load_info_t
*out_info
)
483 err
= load_genericthread(threadcmd
, LC_THREAD
, &customstack
, out_info
);
486 print("bad executable (stackless thread has stack)\n");
494 Loads a Mach-O executable into memory, along with any threads,
495 stacks, and dylinker.
496 Returns 0 on success, -1 on any failure.
497 fd[offset..offset+size) is a Mach-O thin file.
498 filetype is MH_EXECUTE or MH_DYLINKER.
499 The mapped but empty stack is returned in out_info->stack_start.
500 The executable's Mach headers are returned in out_info->text.
501 The executable's entry point is returned in out_info->entry.
502 The dylinker's entry point (if any) is returned in out_info->linker_entry.
503 The dylinker's offset (macOS 10.12) is returned in out_info->linker_offset.
504 GrP fixme need to return whether dylinker was found - stack layout is different
507 load_thin_file(int fd
, vki_off_t offset
, vki_off_t size
, unsigned long filetype
,
508 const HChar
*filename
, load_info_t
*out_info
)
510 VG_(debugLog
)(1, "ume", "load_thin_file: begin: %s\n", filename
);
511 struct MACH_HEADER mh
;
512 vki_uint8_t
*headers
;
513 vki_uint8_t
*headers_end
;
514 struct load_command
*lc
;
515 struct load_command
*lcend
;
516 struct SEGMENT_COMMAND
*segcmd
;
517 struct thread_command
*threadcmd
;
518 struct dylinker_command
*dycmd
;
523 // Read Mach-O header
524 if (sizeof(mh
) > size
) {
525 print("bad executable (no Mach-O header)\n");
527 res
= VG_(pread
)(fd
, &mh
, sizeof(mh
), offset
);
528 if (sr_isError(res
) || sr_Res(res
) != sizeof(mh
)) {
529 print("bad executable (no Mach-O header)\n");
534 // Sanity-check the header itself
535 if (mh
.magic
!= MAGIC
) {
536 print("bad executable (no Mach-O magic)\n");
540 if (mh
.filetype
!= filetype
) {
541 // expecting MH_EXECUTE or MH_DYLINKER
542 print("bad executable (wrong file type)\n");
547 // Map all headers into memory
548 len
= sizeof(mh
) + mh
.sizeofcmds
;
550 print("bad executable (missing load commands)\n");
554 headers
= VG_(malloc
)("ume.macho.headers", len
);
555 res
= VG_(pread
)(fd
, headers
, len
, offset
);
556 if (sr_isError(res
)) {
557 print("couldn't read load commands from executable\n");
560 headers_end
= headers
+ len
;
563 // Map some segments into client memory:
564 // LC_SEGMENT (text, data, etc)
566 // LOAD_DYLINKER (dyld)
567 lcend
= (struct load_command
*)(headers
+ mh
.sizeofcmds
+ sizeof(mh
));
568 for (lc
= (struct load_command
*)(headers
+ sizeof(mh
));
570 lc
= (struct load_command
*)(lc
->cmdsize
+ (vki_uint8_t
*)lc
))
572 if ((vki_uint8_t
*)lc
< headers
||
573 lc
->cmdsize
+(vki_uint8_t
*)lc
> headers_end
) {
574 print("bad executable (invalid load commands)\n");
580 #if DARWIN_VERS >= DARWIN_10_8
581 case LC_MAIN
: { /* New in 10.8 */
582 struct entry_point_command
* epcmd
583 = (struct entry_point_command
*)lc
;
584 if (out_info
->stack_start
|| out_info
->stack_end
) {
585 print("bad executable (multiple indications of stack)");
588 err
= handle_lcmain(epcmd
->stacksize
, out_info
);
590 VG_(debugLog
)(2, "ume", "lc_main: created stack %p-%p\n",
591 out_info
->stack_start
, out_info
->stack_end
);
597 if (lc
->cmdsize
< sizeof(struct SEGMENT_COMMAND
)) {
598 print("bad executable (invalid load commands)\n");
601 segcmd
= (struct SEGMENT_COMMAND
*)lc
;
602 #if DARWIN_VERS >= DARWIN_10_12
603 /* dyld text address is relative instead of absolute in 10.12 */
604 if (filetype
== MH_DYLINKER
&& segcmd
->vmaddr
== 0 && segcmd
->fileoff
== 0) {
605 out_info
->linker_offset
= out_info
->max_addr
;
608 err
= load_segment(fd
, offset
, size
, segcmd
, filename
, out_info
);
614 if (out_info
->stack_end
|| out_info
->entry
) {
615 print("bad executable (multiple thread commands)\n");
618 if (lc
->cmdsize
< sizeof(struct thread_command
)) {
619 print("bad executable (invalid load commands)\n");
622 threadcmd
= (struct thread_command
*)lc
;
623 err
= load_unixthread(threadcmd
, out_info
);
627 case LC_LOAD_DYLINKER
:
628 if (filetype
== MH_DYLINKER
) {
629 print("bad executable (dylinker needs a dylinker)\n");
632 if (out_info
->linker_entry
) {
633 print("bad executable (multiple dylinker commands)\n");
635 if (lc
->cmdsize
< sizeof(struct dylinker_command
)) {
636 print("bad executable (invalid load commands)\n");
639 dycmd
= (struct dylinker_command
*)lc
;
640 err
= load_dylinker(dycmd
, out_info
);
645 if (filetype
== MH_EXECUTE
) {
646 print("bad executable (stackless thread)\n");
649 if (out_info
->stack_end
|| out_info
->entry
) {
650 print("bad executable (multiple thread commands)\n");
653 if (lc
->cmdsize
< sizeof(struct thread_command
)) {
654 print("bad executable (invalid load commands)\n");
657 threadcmd
= (struct thread_command
*)lc
;
658 err
= load_thread(threadcmd
, out_info
);
668 // Done with the headers
671 if (filetype
== MH_EXECUTE
) {
672 // Verify the necessary pieces for an executable:
675 // an entry point (static or linker)
676 if (!out_info
->stack_end
|| !out_info
->stack_start
) {
677 VG_(printf
)("bad executable %s (no stack)\n", filename
);
680 if (!out_info
->text
) {
681 print("bad executable (no text segment)\n");
684 if (!out_info
->entry
&& !out_info
->linker_entry
) {
685 print("bad executable (no entry point)\n");
689 else if (filetype
== MH_DYLINKER
) {
690 // Verify the necessary pieces for a dylinker:
692 if (!out_info
->entry
) {
693 print("bad executable (no entry point)\n");
698 VG_(debugLog
)(1, "ume", "load_thin_file: success: %s\n", filename
);
704 Load a fat Mach-O executable.
707 load_fat_file(int fd
, vki_off_t offset
, vki_off_t size
, unsigned long filetype
,
708 const HChar
*filename
, load_info_t
*out_info
)
710 struct fat_header fh
;
711 vki_off_t arch_offset
;
713 cpu_type_t good_arch
;
716 #if defined(VGA_ppc32)
717 good_arch
= CPU_TYPE_POWERPC
;
718 #elif defined(VGA_ppc64be)
719 good_arch
= CPU_TYPE_POWERPC64BE
;
720 #elif defined(VGA_ppc64le)
721 good_arch
= CPU_TYPE_POWERPC64LE
;
722 #elif defined(VGA_x86)
723 good_arch
= CPU_TYPE_I386
;
724 #elif defined(VGA_amd64)
725 good_arch
= CPU_TYPE_X86_64
;
727 # error unknown architecture
731 // All fat contents are BIG-ENDIAN
732 if (size
< sizeof(fh
)) {
733 print("bad executable (bad fat header)\n");
736 res
= VG_(pread
)(fd
, &fh
, sizeof(fh
), offset
);
737 if (sr_isError(res
) || sr_Res(res
) != sizeof(fh
)) {
738 print("bad executable (bad fat header)\n");
742 // Scan arch headers looking for a good one
743 arch_offset
= offset
+ sizeof(fh
);
744 fh
.nfat_arch
= VG_(ntohl
)(fh
.nfat_arch
);
745 for (i
= 0; i
< fh
.nfat_arch
; i
++) {
746 struct fat_arch arch
;
747 if (arch_offset
+ sizeof(arch
) > size
) {
748 print("bad executable (corrupt fat archs)\n");
752 res
= VG_(pread
)(fd
, &arch
, sizeof(arch
), arch_offset
);
753 arch_offset
+= sizeof(arch
);
754 if (sr_isError(res
) || sr_Res(res
) != sizeof(arch
)) {
755 VG_(printf
)("bad executable (corrupt fat arch) %x %llu\n",
756 arch
.cputype
, (ULong
)arch_offset
);
760 arch
.cputype
= VG_(ntohl
)(arch
.cputype
);
761 arch
.cpusubtype
= VG_(ntohl
)(arch
.cpusubtype
);
762 arch
.offset
= VG_(ntohl
)(arch
.offset
);
763 arch
.size
= VG_(ntohl
)(arch
.size
);
764 arch
.align
= VG_(ntohl
)(arch
.align
);
765 if (arch
.cputype
== good_arch
) {
767 if (arch
.offset
> size
|| arch
.offset
+ arch
.size
> size
) {
768 print("bad executable (corrupt fat arch 2)\n");
771 return load_mach_file(fd
, offset
+arch
.offset
, arch
.size
, filetype
, filename
, out_info
);
775 print("bad executable (can't run on this machine)\n");
780 Load a Mach-O executable or dylinker.
781 The file may be fat or thin.
784 load_mach_file(int fd
, vki_off_t offset
, vki_off_t size
, unsigned long filetype
,
785 const HChar
*filename
, load_info_t
*out_info
)
790 if (size
< sizeof(magic
)) {
791 print("bad executable (no Mach-O magic)\n");
794 res
= VG_(pread
)(fd
, &magic
, sizeof(magic
), offset
);
795 if (sr_isError(res
) || sr_Res(res
) != sizeof(magic
)) {
796 print("bad executable (no Mach-O magic)\n");
800 if (magic
== MAGIC
) {
802 return load_thin_file(fd
, offset
, size
, filetype
, filename
, out_info
);
803 } else if (magic
== VG_(htonl
)(FAT_MAGIC
)) {
805 return load_fat_file(fd
, offset
, size
, filetype
, filename
, out_info
);
808 print("bad executable (bad Mach-O magic)\n");
814 Bool
VG_(match_macho
)(const void *hdr
, SizeT len
)
816 const vki_uint32_t
*magic
= hdr
;
818 // GrP fixme check more carefully for matching fat arch?
820 return (len
>= VKI_PAGE_SIZE
&&
821 (*magic
== MAGIC
|| *magic
== VG_(ntohl
)(FAT_MAGIC
)))
826 Int
VG_(load_macho
)(Int fd
, const HChar
*name
, ExeInfo
*info
)
830 load_info_t load_info
;
831 load_info
.stack_start
= NULL
;
832 load_info
.stack_end
= NULL
;
833 load_info
.text
= NULL
;
834 load_info
.entry
= NULL
;
835 load_info
.linker_entry
= NULL
;
836 load_info
.linker_offset
= 0;
837 load_info
.max_addr
= 0;
839 err
= VG_(fstat
)(fd
, &sb
);
841 print("couldn't stat executable\n");
845 err
= load_mach_file(fd
, 0, sb
.size
, MH_EXECUTE
, name
, &load_info
);
846 if (err
) return VKI_ENOEXEC
;
848 // GrP fixme exe_base
850 info
->entry
= (Addr
) load_info
.entry
;
851 info
->init_ip
= (Addr
)(load_info
.linker_entry
? load_info
.linker_entry
: load_info
.entry
);
852 info
->brkbase
= 0xffffffff; // GrP fixme hack
853 info
->init_toc
= 0; // GrP fixme unused
855 info
->stack_start
= (Addr
) load_info
.stack_start
;
856 info
->stack_end
= (Addr
) load_info
.stack_end
;
857 info
->text
= (Addr
) load_info
.text
;
858 info
->dynamic
= load_info
.linker_entry
? True
: False
;
860 info
->executable_path
= VG_(strdup
)("ume.macho.executable_path", name
);
865 #endif // defined(VGO_darwin)
867 /*--------------------------------------------------------------------*/
869 /*--------------------------------------------------------------------*/