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, see <http://www.gnu.org/licenses/>.
26 The GNU General Public License is contained in the file COPYING.
29 #if defined(VGO_darwin)
31 #include "pub_core_basics.h"
32 #include "pub_core_vki.h"
34 #include "pub_core_aspacemgr.h" // various mapping fns
35 #include "pub_core_debuglog.h"
36 #include "pub_core_libcassert.h" // VG_(exit), vg_assert
37 #include "pub_core_libcbase.h" // VG_(memcmp), etc
38 #include "pub_core_libcfile.h" // VG_(open) et al
39 #include "pub_core_libcprint.h"
40 #include "pub_core_libcproc.h"
41 #include "pub_core_machine.h" // VG_ELF_CLASS (XXX: which should be moved)
42 #include "pub_core_mallocfree.h" // VG_(malloc), VG_(free)
43 #include "pub_core_syscall.h" // VG_(strerror)
44 #include "pub_core_ume.h" // self
48 #include <mach/mach.h>
50 #include <mach-o/dyld.h>
51 #include <mach-o/fat.h>
52 #include <mach-o/loader.h>
55 #define MAGIC MH_MAGIC
56 #define MACH_HEADER mach_header
57 #define LC_SEGMENT_CMD LC_SEGMENT
58 #define SEGMENT_COMMAND segment_command
59 #define SECTION section
61 #define MAGIC MH_MAGIC_64
62 #define MACH_HEADER mach_header_64
63 #define LC_SEGMENT_CMD LC_SEGMENT_64
64 #define SEGMENT_COMMAND segment_command_64
65 #define SECTION section_64
68 typedef struct load_info_t
{
69 vki_uint8_t
*stack_start
; // allocated thread stack (hot end)
70 vki_uint8_t
*stack_end
; // allocated thread stack (cold end)
71 vki_uint8_t
*text
; // start of text segment (i.e. the mach headers)
72 vki_uint8_t
*entry
; // static entry point
73 vki_uint8_t
*linker_entry
; // dylinker entry point
74 Addr linker_offset
; // dylinker text offset
75 vki_size_t max_addr
; // biggest address reached while loading segments
78 static void print(const HChar
*str
)
80 VG_(printf
)("%s", str
);
83 static void check_mmap(SysRes res
, Addr base
, SizeT len
, const HChar
* who
)
85 if (sr_isError(res
)) {
86 VG_(printf
)("valgrind: mmap-FIXED(0x%llx, %lld) failed in UME (%s) "
87 "with error %lu (%s).\n",
88 (ULong
)base
, (Long
)len
, who
,
89 sr_Err(res
), VG_(strerror
)(sr_Err(res
)) );
94 #if DARWIN_VERS >= DARWIN_10_8
95 static void check_mmap_float(SysRes res
, SizeT len
, const HChar
* who
)
97 if (sr_isError(res
)) {
98 VG_(printf
)("valgrind: mmap-FLOAT(size=%lld) failed in UME (%s) "
99 "with error %lu (%s).\n",
101 sr_Err(res
), VG_(strerror
)(sr_Err(res
)) );
108 load_thin_file(int fd
, vki_off_t offset
, vki_off_t size
, unsigned long filetype
,
109 const HChar
*filename
, load_info_t
*out_info
);
112 load_fat_file(int fd
, vki_off_t offset
, vki_off_t size
, unsigned long filetype
,
113 const HChar
*filename
, load_info_t
*out_info
);
116 load_mach_file(int fd
, vki_off_t offset
, vki_off_t size
, unsigned long filetype
,
117 const HChar
*filename
, load_info_t
*out_info
);
120 /* Open and map a dylinker file.
121 Returns 0 on success, -1 on any failure.
122 filename must be an absolute path.
123 The dylinker's entry point is returned in out_info->linker_entry.
126 open_dylinker(const HChar
*filename
, load_info_t
*out_info
)
134 if (filename
[0] != '/') {
135 print("bad executable (dylinker name is not an absolute path)\n");
139 res
= VG_(open
)(filename
, VKI_O_RDONLY
, 0);
141 if (sr_isError(res
)) {
142 VG_(printf
)("couldn't open dylinker: %s\n", filename
);
145 err
= VG_(fstat
)(fd
, &sb
);
147 VG_(printf
)("couldn't stat dylinker: %s\n", filename
);
153 err
= load_mach_file(fd
, 0, filesize
, MH_DYLINKER
, filename
, out_info
);
155 VG_(printf
)("...while loading dylinker: %s\n", filename
);
163 Process an LC_SEGMENT command, mapping it into memory if appropriate.
164 fd[offset..size) is a Mach-O thin file.
165 Returns 0 on success, -1 on any failure.
166 If this segment contains the executable's Mach headers, their
167 loaded address is returned in out_info->text.
168 If this segment is a __UNIXSTACK, its start address is returned in
169 out_info->stack_start.
172 load_segment(int fd
, vki_off_t offset
, vki_off_t size
,
173 struct SEGMENT_COMMAND
*segcmd
, const HChar
*filename
,
174 load_info_t
*out_info
)
178 vki_size_t filesize
; // page-aligned
179 vki_size_t vmsize
; // page-aligned
180 vki_size_t vmend
; // page-aligned
182 Addr slided_addr
= segcmd
->vmaddr
+ out_info
->linker_offset
;
184 // GrP fixme mark __UNIXSTACK as SF_STACK
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.
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");
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");
209 // Record the segment containing the Mach headers themselves
210 if (segcmd
->fileoff
== 0 && segcmd
->filesize
!= 0) {
211 out_info
->text
= (vki_uint8_t
*)slided_addr
;
214 // Record the __UNIXSTACK start
215 if (0 == VG_(strcmp
)(segcmd
->segname
, SEG_UNIXSTACK
)) {
216 out_info
->stack_start
= (vki_uint8_t
*)slided_addr
;
219 // Sanity-check the segment
220 if (segcmd
->fileoff
+ segcmd
->filesize
> size
) {
221 print("bad executable (invalid segment command)\n");
225 vmend
= VG_PGROUNDUP(slided_addr
+ segcmd
->vmsize
);
226 if (vmend
> out_info
->max_addr
) {
227 out_info
->max_addr
= vmend
;
230 if (segcmd
->vmsize
== 0) {
231 return 0; // nothing to map - ok
234 // Get desired memory protection
235 // GrP fixme need maxprot too
236 prot
= (((segcmd
->initprot
& VM_PROT_READ
) ? VKI_PROT_READ
: 0) |
237 ((segcmd
->initprot
& VM_PROT_WRITE
) ? VKI_PROT_WRITE
: 0) |
238 ((segcmd
->initprot
& VM_PROT_EXECUTE
) ? VKI_PROT_EXEC
: 0));
241 filesize
= VG_PGROUNDUP(segcmd
->filesize
);
242 vmsize
= VG_PGROUNDUP(segcmd
->vmsize
);
245 VG_(debugLog
)(2, "ume", "mmap fixed (file) (%#lx, %lu)\n", addr
, filesize
);
246 res
= VG_(am_mmap_named_file_fixed_client
)(addr
, filesize
, prot
, fd
,
247 offset
+ segcmd
->fileoff
,
249 check_mmap(res
, addr
, filesize
, "load_segment1");
252 // Zero-fill the remainder of the segment, if any
253 if (segcmd
->filesize
!= filesize
) {
254 // non-page-aligned part
255 // GrP fixme kernel doesn't do this?
256 //bzero(segcmd->filesize+(vki_uint8_t *)addr, filesize-segcmd->filesize);
258 if (filesize
!= vmsize
) {
260 SizeT length
= vmsize
- filesize
;
261 addr
= (Addr
)(filesize
+ slided_addr
);
262 VG_(debugLog
)(2, "ume", "mmap fixed (anon) (%#lx, %lu)\n", addr
, length
);
263 res
= VG_(am_mmap_anon_fixed_client
)(addr
, length
, prot
);
264 check_mmap(res
, addr
, length
, "load_segment2");
272 Parse a LC_THREAD or LC_UNIXTHREAD command.
273 Return 0 on success, -1 on any failure.
274 If the thread is a LC_UNIXTHREAD, the stack address is returned in out_info->stack_end.
275 If the executable requested a non-default stack address,
276 *customstack is set to TRUE. The thread's entry point is returned in out_info->entry.
277 The stack itself (if any) is not mapped.
278 Other custom register settings are silently ignored (GrP fixme).
281 load_genericthread(struct thread_command
*threadcmd
, int type
,
282 int *customstack
, load_info_t
*out_info
)
289 p
= (unsigned int *)(threadcmd
+ 1);
290 left
= (threadcmd
->cmdsize
- sizeof(struct thread_command
)) / sizeof(*p
);
294 print("bad executable (invalid thread command)\n");
297 flavor
= *p
++; left
--;
298 count
= *p
++; left
--;
301 print("bad executable (invalid thread command 2)\n");
306 if (flavor
== i386_THREAD_STATE
&& count
== i386_THREAD_STATE_COUNT
) {
307 i386_thread_state_t
*state
= (i386_thread_state_t
*)p
;
308 out_info
->entry
= (vki_uint8_t
*)state
->__eip
;
309 if (type
== LC_UNIXTHREAD
) {
310 out_info
->stack_end
=
311 (vki_uint8_t
*)(state
->__esp
? state
->__esp
: VKI_USRSTACK
);
312 vg_assert(VG_IS_PAGE_ALIGNED(out_info
->stack_end
));
313 out_info
->stack_end
--;
315 if (customstack
) *customstack
= state
->__esp
;
319 #elif defined(VGA_amd64)
320 if (flavor
== x86_THREAD_STATE64
&& count
== x86_THREAD_STATE64_COUNT
){
321 x86_thread_state64_t
*state
= (x86_thread_state64_t
*)p
;
322 out_info
->entry
= (vki_uint8_t
*)state
->__rip
;
323 if (type
== LC_UNIXTHREAD
) {
324 out_info
->stack_end
=
325 (vki_uint8_t
*)(state
->__rsp
? state
->__rsp
: VKI_USRSTACK64
);
326 vg_assert(VG_IS_PAGE_ALIGNED(out_info
->stack_end
));
327 out_info
->stack_end
--;
329 if (customstack
) *customstack
= state
->__rsp
;
334 # error unknown platform
340 print("bad executable (no arch-compatible thread state)\n");
345 /* Returns the main stack size on this platform,
346 using getrlimit or a fixed size.
348 static vki_size_t
default_stack_size(void)
350 struct vki_rlimit lim
;
351 int err
= VG_(getrlimit
)(VKI_RLIMIT_STACK
, &lim
);
352 if (err
) return 8*1024*1024; // 8 MB
353 else return lim
.rlim_cur
;
358 Processes a LC_UNIXTHREAD command.
359 Returns 0 on success, -1 on any failure.
360 The stack is mapped in and returned in out_info->stack_start and out_info->stack_end.
361 The thread's entry point is returned in out_info->entry.
364 load_unixthread(struct thread_command
*threadcmd
, load_info_t
*out_info
)
369 err
= load_genericthread(threadcmd
, LC_UNIXTHREAD
, &customstack
, out_info
);
372 if (!out_info
->stack_end
) {
373 print("bad executable (no thread stack)\n");
379 vki_size_t stacksize
= VG_PGROUNDUP(default_stack_size());
380 vm_address_t stackbase
= VG_PGROUNDDN(out_info
->stack_end
+1-stacksize
);
383 res
= VG_(am_mmap_anon_fixed_client
)(stackbase
, stacksize
, VKI_PROT_READ
|VKI_PROT_WRITE
|VKI_PROT_EXEC
);
384 check_mmap(res
, stackbase
, stacksize
, "load_unixthread1");
385 out_info
->stack_start
= (vki_uint8_t
*)stackbase
;
387 // custom stack - mapped via __UNIXTHREAD segment
394 /* Allocates a stack mapping at a V-chosen address. Pertains to
395 LC_MAIN commands, which seem to have appeared in OSX 10.8.
397 This is a really nasty hack -- allocates 64M+stack size, then
398 deallocates the 64M, to guarantee that the stack is at least 64M
400 #if DARWIN_VERS >= DARWIN_10_8
402 handle_lcmain ( vki_size_t requested_size
,
403 load_info_t
*out_info
)
405 if (requested_size
== 0) {
406 requested_size
= default_stack_size();
408 requested_size
= VG_PGROUNDUP(requested_size
);
410 const vki_size_t HACK
= 64 * 1024 * 1024;
411 requested_size
+= HACK
;
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_info
->stack_start
= (vki_uint8_t
*)sr_Res(res
);
418 out_info
->stack_end
= out_info
->stack_start
+ requested_size
- 1;
420 Bool need_discard
= False
;
421 res
= VG_(am_munmap_client
)(&need_discard
, (Addr
)out_info
->stack_start
, HACK
);
422 if (sr_isError(res
)) return -1;
423 vg_assert(!need_discard
); // True == wtf?
425 out_info
->stack_start
+= HACK
;
429 #endif /* DARWIN_VERS >= DARWIN_10_8 */
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 out_info->linker_entry.
440 load_dylinker(struct dylinker_command
*dycmd
, load_info_t
*out_info
)
444 load_info_t linker_info
;
445 linker_info
.stack_start
= NULL
;
446 linker_info
.stack_end
= NULL
;
447 linker_info
.text
= NULL
;
448 linker_info
.entry
= NULL
;
449 linker_info
.linker_entry
= NULL
;
450 linker_info
.linker_offset
= 0;
451 linker_info
.max_addr
= out_info
->max_addr
;
453 if (dycmd
->name
.offset
>= dycmd
->cmdsize
) {
454 print("bad executable (invalid dylinker command)\n");
458 name
= dycmd
->name
.offset
+ (HChar
*)dycmd
;
460 // GrP fixme assumes name is terminated somewhere
461 ret
= open_dylinker(name
, &linker_info
);
462 if (linker_info
.entry
) {
463 out_info
->linker_entry
= linker_info
.entry
+ linker_info
.linker_offset
;
465 out_info
->max_addr
= linker_info
.max_addr
;
471 Process an LC_THREAD command.
472 Returns 0 on success, -1 on any failure.
473 The thread's entry point is returned in out_info->entry.
476 load_thread(struct thread_command
*threadcmd
, load_info_t
*out_info
)
481 err
= load_genericthread(threadcmd
, LC_THREAD
, &customstack
, out_info
);
484 print("bad executable (stackless thread has stack)\n");
492 Loads a Mach-O executable into memory, along with any threads,
493 stacks, and dylinker.
494 Returns 0 on success, -1 on any failure.
495 fd[offset..offset+size) is a Mach-O thin file.
496 filetype is MH_EXECUTE or MH_DYLINKER.
497 The mapped but empty stack is returned in out_info->stack_start.
498 The executable's Mach headers are returned in out_info->text.
499 The executable's entry point is returned in out_info->entry.
500 The dylinker's entry point (if any) is returned in out_info->linker_entry.
501 The dylinker's offset (macOS 10.12) is returned in out_info->linker_offset.
502 GrP fixme need to return whether dylinker was found - stack layout is different
505 load_thin_file(int fd
, vki_off_t offset
, vki_off_t size
, unsigned long filetype
,
506 const HChar
*filename
, load_info_t
*out_info
)
508 VG_(debugLog
)(1, "ume", "load_thin_file: begin: %s\n", filename
);
509 struct MACH_HEADER mh
;
510 vki_uint8_t
*headers
;
511 vki_uint8_t
*headers_end
;
512 struct load_command
*lc
;
513 struct load_command
*lcend
;
514 struct SEGMENT_COMMAND
*segcmd
;
515 struct thread_command
*threadcmd
;
516 struct dylinker_command
*dycmd
;
521 // Read Mach-O header
522 if (sizeof(mh
) > size
) {
523 print("bad executable (no Mach-O header)\n");
525 res
= VG_(pread
)(fd
, &mh
, sizeof(mh
), offset
);
526 if (sr_isError(res
) || sr_Res(res
) != sizeof(mh
)) {
527 print("bad executable (no Mach-O header)\n");
532 // Sanity-check the header itself
533 if (mh
.magic
!= MAGIC
) {
534 print("bad executable (no Mach-O magic)\n");
538 if (mh
.filetype
!= filetype
) {
539 // expecting MH_EXECUTE or MH_DYLINKER
540 print("bad executable (wrong file type)\n");
545 // Map all headers into memory
546 len
= sizeof(mh
) + mh
.sizeofcmds
;
548 print("bad executable (missing load commands)\n");
552 headers
= VG_(malloc
)("ume.macho.headers", len
);
553 res
= VG_(pread
)(fd
, headers
, len
, offset
);
554 if (sr_isError(res
)) {
555 print("couldn't read load commands from executable\n");
558 headers_end
= headers
+ len
;
561 // Map some segments into client memory:
562 // LC_SEGMENT (text, data, etc)
564 // LOAD_DYLINKER (dyld)
565 lcend
= (struct load_command
*)(headers
+ mh
.sizeofcmds
+ sizeof(mh
));
566 for (lc
= (struct load_command
*)(headers
+ sizeof(mh
));
568 lc
= (struct load_command
*)(lc
->cmdsize
+ (vki_uint8_t
*)lc
))
570 if ((vki_uint8_t
*)lc
< headers
||
571 lc
->cmdsize
+(vki_uint8_t
*)lc
> headers_end
) {
572 print("bad executable (invalid load commands)\n");
578 #if DARWIN_VERS >= DARWIN_10_8
579 case LC_MAIN
: { /* New in 10.8 */
580 struct entry_point_command
* epcmd
581 = (struct entry_point_command
*)lc
;
582 if (out_info
->stack_start
|| out_info
->stack_end
) {
583 print("bad executable (multiple indications of stack)");
586 err
= handle_lcmain(epcmd
->stacksize
, out_info
);
588 VG_(debugLog
)(2, "ume", "lc_main: created stack %p-%p\n",
589 out_info
->stack_start
, out_info
->stack_end
);
595 if (lc
->cmdsize
< sizeof(struct SEGMENT_COMMAND
)) {
596 print("bad executable (invalid load commands)\n");
599 segcmd
= (struct SEGMENT_COMMAND
*)lc
;
600 #if DARWIN_VERS >= DARWIN_10_12
601 /* dyld text address is relative instead of absolute in 10.12 */
602 if (filetype
== MH_DYLINKER
&& segcmd
->vmaddr
== 0 && segcmd
->fileoff
== 0) {
603 out_info
->linker_offset
= out_info
->max_addr
;
606 err
= load_segment(fd
, offset
, size
, segcmd
, filename
, out_info
);
612 if (out_info
->stack_end
|| out_info
->entry
) {
613 print("bad executable (multiple thread commands)\n");
616 if (lc
->cmdsize
< sizeof(struct thread_command
)) {
617 print("bad executable (invalid load commands)\n");
620 threadcmd
= (struct thread_command
*)lc
;
621 err
= load_unixthread(threadcmd
, out_info
);
625 case LC_LOAD_DYLINKER
:
626 if (filetype
== MH_DYLINKER
) {
627 print("bad executable (dylinker needs a dylinker)\n");
630 if (out_info
->linker_entry
) {
631 print("bad executable (multiple dylinker commands)\n");
633 if (lc
->cmdsize
< sizeof(struct dylinker_command
)) {
634 print("bad executable (invalid load commands)\n");
637 dycmd
= (struct dylinker_command
*)lc
;
638 err
= load_dylinker(dycmd
, out_info
);
643 if (filetype
== MH_EXECUTE
) {
644 print("bad executable (stackless thread)\n");
647 if (out_info
->stack_end
|| out_info
->entry
) {
648 print("bad executable (multiple thread commands)\n");
651 if (lc
->cmdsize
< sizeof(struct thread_command
)) {
652 print("bad executable (invalid load commands)\n");
655 threadcmd
= (struct thread_command
*)lc
;
656 err
= load_thread(threadcmd
, out_info
);
666 // Done with the headers
669 if (filetype
== MH_EXECUTE
) {
670 // Verify the necessary pieces for an executable:
673 // an entry point (static or linker)
674 if (!out_info
->stack_end
|| !out_info
->stack_start
) {
675 VG_(printf
)("bad executable %s (no stack)\n", filename
);
678 if (!out_info
->text
) {
679 print("bad executable (no text segment)\n");
682 if (!out_info
->entry
&& !out_info
->linker_entry
) {
683 print("bad executable (no entry point)\n");
687 else if (filetype
== MH_DYLINKER
) {
688 // Verify the necessary pieces for a dylinker:
690 if (!out_info
->entry
) {
691 print("bad executable (no entry point)\n");
696 VG_(debugLog
)(1, "ume", "load_thin_file: success: %s\n", filename
);
702 Load a fat Mach-O executable.
705 load_fat_file(int fd
, vki_off_t offset
, vki_off_t size
, unsigned long filetype
,
706 const HChar
*filename
, load_info_t
*out_info
)
708 struct fat_header fh
;
709 vki_off_t arch_offset
;
711 cpu_type_t good_arch
;
714 #if defined(VGA_ppc32)
715 good_arch
= CPU_TYPE_POWERPC
;
716 #elif defined(VGA_ppc64be)
717 good_arch
= CPU_TYPE_POWERPC64BE
;
718 #elif defined(VGA_ppc64le)
719 good_arch
= CPU_TYPE_POWERPC64LE
;
720 #elif defined(VGA_x86)
721 good_arch
= CPU_TYPE_I386
;
722 #elif defined(VGA_amd64)
723 good_arch
= CPU_TYPE_X86_64
;
725 # error unknown architecture
729 // All fat contents are BIG-ENDIAN
730 if (size
< sizeof(fh
)) {
731 print("bad executable (bad fat header)\n");
734 res
= VG_(pread
)(fd
, &fh
, sizeof(fh
), offset
);
735 if (sr_isError(res
) || sr_Res(res
) != sizeof(fh
)) {
736 print("bad executable (bad fat header)\n");
740 // Scan arch headers looking for a good one
741 arch_offset
= offset
+ sizeof(fh
);
742 fh
.nfat_arch
= VG_(ntohl
)(fh
.nfat_arch
);
743 for (i
= 0; i
< fh
.nfat_arch
; i
++) {
744 struct fat_arch arch
;
745 if (arch_offset
+ sizeof(arch
) > size
) {
746 print("bad executable (corrupt fat archs)\n");
750 res
= VG_(pread
)(fd
, &arch
, sizeof(arch
), arch_offset
);
751 arch_offset
+= sizeof(arch
);
752 if (sr_isError(res
) || sr_Res(res
) != sizeof(arch
)) {
753 VG_(printf
)("bad executable (corrupt fat arch) %x %llu\n",
754 arch
.cputype
, (ULong
)arch_offset
);
758 arch
.cputype
= VG_(ntohl
)(arch
.cputype
);
759 arch
.cpusubtype
= VG_(ntohl
)(arch
.cpusubtype
);
760 arch
.offset
= VG_(ntohl
)(arch
.offset
);
761 arch
.size
= VG_(ntohl
)(arch
.size
);
762 arch
.align
= VG_(ntohl
)(arch
.align
);
763 if (arch
.cputype
== good_arch
) {
765 if (arch
.offset
> size
|| arch
.offset
+ arch
.size
> size
) {
766 print("bad executable (corrupt fat arch 2)\n");
769 return load_mach_file(fd
, offset
+arch
.offset
, arch
.size
, filetype
, filename
, out_info
);
773 print("bad executable (can't run on this machine)\n");
778 Load a Mach-O executable or dylinker.
779 The file may be fat or thin.
782 load_mach_file(int fd
, vki_off_t offset
, vki_off_t size
, unsigned long filetype
,
783 const HChar
*filename
, load_info_t
*out_info
)
788 if (size
< sizeof(magic
)) {
789 print("bad executable (no Mach-O magic)\n");
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");
798 if (magic
== MAGIC
) {
800 return load_thin_file(fd
, offset
, size
, filetype
, filename
, out_info
);
801 } else if (magic
== VG_(htonl
)(FAT_MAGIC
)) {
803 return load_fat_file(fd
, offset
, size
, filetype
, filename
, out_info
);
806 print("bad executable (bad Mach-O magic)\n");
812 Bool
VG_(match_macho
)(const void *hdr
, SizeT len
)
814 const vki_uint32_t
*magic
= hdr
;
816 // GrP fixme check more carefully for matching fat arch?
818 return (len
>= VKI_PAGE_SIZE
&&
819 (*magic
== MAGIC
|| *magic
== VG_(ntohl
)(FAT_MAGIC
)))
824 Int
VG_(load_macho
)(Int fd
, const HChar
*name
, ExeInfo
*info
)
828 load_info_t load_info
;
829 load_info
.stack_start
= NULL
;
830 load_info
.stack_end
= NULL
;
831 load_info
.text
= NULL
;
832 load_info
.entry
= NULL
;
833 load_info
.linker_entry
= NULL
;
834 load_info
.linker_offset
= 0;
835 load_info
.max_addr
= 0;
837 err
= VG_(fstat
)(fd
, &sb
);
839 print("couldn't stat executable\n");
843 err
= load_mach_file(fd
, 0, sb
.size
, MH_EXECUTE
, name
, &load_info
);
844 if (err
) return VKI_ENOEXEC
;
846 // GrP fixme exe_base
848 info
->entry
= (Addr
) load_info
.entry
;
849 info
->init_ip
= (Addr
)(load_info
.linker_entry
? load_info
.linker_entry
: load_info
.entry
);
850 info
->brkbase
= 0xffffffff; // GrP fixme hack
851 info
->init_toc
= 0; // GrP fixme unused
853 info
->stack_start
= (Addr
) load_info
.stack_start
;
854 info
->stack_end
= (Addr
) load_info
.stack_end
;
855 info
->text
= (Addr
) load_info
.text
;
856 info
->dynamic
= load_info
.linker_entry
? True
: False
;
858 info
->executable_path
= VG_(strdup
)("ume.macho.executable_path", name
);
863 #endif // defined(VGO_darwin)
865 /*--------------------------------------------------------------------*/
867 /*--------------------------------------------------------------------*/