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-2010 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 char * str)71 static void print(const char *str)
72 {
73 VG_(printf)("%s", str);
74 }
75
check_mmap(SysRes res,Addr base,SizeT len,HChar * who)76 static void check_mmap(SysRes res, Addr base, SizeT len, HChar* who)
77 {
78 if (sr_isError(res)) {
79 VG_(printf)("valgrind: mmap(0x%llx, %lld) failed in UME (%s).\n",
80 (ULong)base, (Long)len, who);
81 VG_(exit)(1);
82 }
83 }
84
85
86 static int
87 load_thin_file(int fd, vki_off_t offset, vki_off_t size, unsigned long filetype,
88 const char *filename,
89 vki_uint8_t **out_stack_start, vki_uint8_t **out_stack_end,
90 vki_uint8_t **out_text, vki_uint8_t **out_entry, vki_uint8_t **out_linker_entry);
91
92 static int
93 load_fat_file(int fd, vki_off_t offset, vki_off_t size, unsigned long filetype,
94 const char *filename,
95 vki_uint8_t **out_stack_start, vki_uint8_t **out_stack_end,
96 vki_uint8_t **out_text, vki_uint8_t **out_entry, vki_uint8_t **out_linker_entry);
97
98 static int
99 load_mach_file(int fd, vki_off_t offset, vki_off_t size, unsigned long filetype,
100 const char *filename,
101 vki_uint8_t **out_stack_start, vki_uint8_t **out_stack_end,
102 vki_uint8_t **out_text, vki_uint8_t **out_entry, vki_uint8_t **out_linker_entry);
103
104
105 /* Open and map a dylinker file.
106 Returns 0 on success, -1 on any failure.
107 filename must be an absolute path.
108 The dylinker's entry point is returned in *out_linker_entry.
109 */
110 static int
open_dylinker(const char * filename,vki_uint8_t ** out_linker_entry)111 open_dylinker(const char *filename, vki_uint8_t **out_linker_entry)
112 {
113 struct vg_stat sb;
114 vki_size_t filesize;
115 SysRes res;
116 int fd;
117 int err;
118
119 if (filename[0] != '/') {
120 print("bad executable (dylinker name is not an absolute path)\n");
121 return -1;
122 }
123
124 res = VG_(open)(filename, VKI_O_RDONLY, 0);
125 fd = sr_Res(res);
126 if (sr_isError(res)) {
127 print("couldn't open dylinker: ");
128 print(filename);
129 print("\n");
130 return -1;
131 }
132 err = VG_(fstat)(fd, &sb);
133 if (err) {
134 print("couldn't stat dylinker: ");
135 print(filename);
136 print("\n");
137 VG_(close)(fd);
138 return -1;
139 }
140 filesize = sb.size;
141
142 err = load_mach_file(fd, 0, filesize, MH_DYLINKER, filename,
143 NULL, NULL, NULL, out_linker_entry, NULL);
144 if (err) {
145 print("...while loading dylinker: ");
146 print(filename);
147 print("\n");
148 }
149 VG_(close)(fd);
150 return err;
151 }
152
153
154 /*
155 Process an LC_SEGMENT command, mapping it into memory if appropriate.
156 fd[offset..size) is a Mach-O thin file.
157 Returns 0 on success, -1 on any failure.
158 If this segment contains the executable's Mach headers, their
159 loaded address is returned in *text.
160 If this segment is a __UNIXSTACK, its start address is returned in
161 *stack_start.
162 */
163 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)164 load_segment(int fd, vki_off_t offset, vki_off_t size,
165 vki_uint8_t **text, vki_uint8_t **stack_start,
166 struct SEGMENT_COMMAND *segcmd, const HChar *filename)
167 {
168 SysRes res;
169 Addr addr;
170 vki_size_t filesize; // page-aligned
171 vki_size_t vmsize; // page-aligned
172 unsigned int prot;
173
174 // GrP fixme mark __UNIXSTACK as SF_STACK
175
176 // Don't honour the client's request to map PAGEZERO. Why not?
177 // Because when the kernel loaded the valgrind tool executable,
178 // it will have mapped pagezero itself. So further attempts
179 // to map it when loading the client are guaranteed to fail.
180 #if VG_WORDSIZE == 4
181 if (segcmd->vmaddr == 0 && 0 == VG_(strcmp)(segcmd->segname, SEG_PAGEZERO)) {
182 if (segcmd->vmsize != 0x1000) {
183 print("bad executable (__PAGEZERO is not 4 KB)\n");
184 return -1;
185 }
186 return 0;
187 }
188 #endif
189 #if VG_WORDSIZE == 8
190 if (segcmd->vmaddr == 0 && 0 == VG_(strcmp)(segcmd->segname, SEG_PAGEZERO)) {
191 if (segcmd->vmsize != 0x100000000) {
192 print("bad executable (__PAGEZERO is not 4 GB)\n");
193 return -1;
194 }
195 return 0;
196 }
197 #endif
198
199 // Record the segment containing the Mach headers themselves
200 if (segcmd->fileoff == 0 && segcmd->filesize != 0) {
201 if (text) *text = (vki_uint8_t *)segcmd->vmaddr;
202 }
203
204 // Record the __UNIXSTACK start
205 if (0 == VG_(strcmp)(segcmd->segname, SEG_UNIXSTACK)) {
206 if (stack_start) *stack_start = (vki_uint8_t *)segcmd->vmaddr;
207 }
208
209 // Sanity-check the segment
210 if (segcmd->fileoff + segcmd->filesize > size) {
211 print("bad executable (invalid segment command)\n");
212 return -1;
213 }
214 if (segcmd->vmsize == 0) {
215 return 0; // nothing to map - ok
216 }
217
218 // Get desired memory protection
219 // GrP fixme need maxprot too
220 prot = (((segcmd->initprot & VM_PROT_READ) ? VKI_PROT_READ : 0) |
221 ((segcmd->initprot & VM_PROT_WRITE) ? VKI_PROT_WRITE : 0) |
222 ((segcmd->initprot & VM_PROT_EXECUTE) ? VKI_PROT_EXEC : 0));
223
224 // Map the segment
225 filesize = VG_PGROUNDUP(segcmd->filesize);
226 vmsize = VG_PGROUNDUP(segcmd->vmsize);
227 if (filesize > 0) {
228 addr = (Addr)segcmd->vmaddr;
229 VG_(debugLog)(2, "ume", "mmap fixed (file) (%#lx, %lu)\n", addr, filesize);
230 res = VG_(am_mmap_named_file_fixed_client)(addr, filesize, prot, fd,
231 offset + segcmd->fileoff,
232 filename);
233 check_mmap(res, addr, filesize, "load_segment1");
234 }
235
236 // Zero-fill the remainder of the segment, if any
237 if (segcmd->filesize != filesize) {
238 // non-page-aligned part
239 // GrP fixme kernel doesn't do this?
240 //bzero(segcmd->filesize+(vki_uint8_t *)addr, filesize-segcmd->filesize);
241 }
242 if (filesize != vmsize) {
243 // page-aligned part
244 SizeT length = vmsize - filesize;
245 addr = (Addr)(filesize + segcmd->vmaddr);
246 VG_(debugLog)(2, "ume", "mmap fixed (anon) (%#lx, %lu)\n", addr, length);
247 res = VG_(am_mmap_anon_fixed_client)(addr, length, prot);
248 check_mmap(res, addr, length, "load_segment2");
249 }
250
251 return 0;
252 }
253
254
255 /*
256 Parse a LC_THREAD or LC_UNIXTHREAD command.
257 Return 0 on success, -1 on any failure.
258 The stack address is returned in *stack. If the executable requested
259 a non-default stack address, *customstack is set to TRUE. The thread's
260 entry point is returned in *entry.
261 The stack itself (if any) is not mapped.
262 Other custom register settings are silently ignored (GrP fixme).
263 */
264 static int
load_genericthread(vki_uint8_t ** stack_end,int * customstack,vki_uint8_t ** entry,struct thread_command * threadcmd)265 load_genericthread(vki_uint8_t **stack_end,
266 int *customstack, vki_uint8_t **entry,
267 struct thread_command *threadcmd)
268 {
269 unsigned int flavor;
270 unsigned int count;
271 unsigned int *p;
272 unsigned int left;
273
274 p = (unsigned int *)(threadcmd + 1);
275 left = (threadcmd->cmdsize - sizeof(struct thread_command)) / sizeof(*p);
276
277 while (left > 0) {
278 if (left < 2) {
279 print("bad executable (invalid thread command)\n");
280 return -1;
281 }
282 flavor = *p++; left--;
283 count = *p++; left--;
284
285 if (left < count) {
286 print("bad executable (invalid thread command 2)\n");
287 return -1;
288 }
289
290 #if defined(VGA_x86)
291 if (flavor == i386_THREAD_STATE && count == i386_THREAD_STATE_COUNT) {
292 i386_thread_state_t *state = (i386_thread_state_t *)p;
293 if (entry) *entry = (vki_uint8_t *)state->__eip;
294 if (stack_end) *stack_end = (vki_uint8_t *)(state->__esp ? state->__esp : VKI_USRSTACK);
295 if (customstack) *customstack = state->__esp;
296 return 0;
297 }
298
299 #elif defined(VGA_amd64)
300 if (flavor == x86_THREAD_STATE64 && count == x86_THREAD_STATE64_COUNT){
301 x86_thread_state64_t *state = (x86_thread_state64_t *)p;
302 if (entry) *entry = (vki_uint8_t *)state->__rip;
303 if (stack_end) *stack_end = (vki_uint8_t *)(state->__rsp ? state->__rsp : VKI_USRSTACK64);
304 if (customstack) *customstack = state->__rsp;
305 return 0;
306 }
307
308 #else
309 # error unknown platform
310 #endif
311 p += count;
312 left -= count;
313 }
314
315 print("bad executable (no arch-compatible thread state)\n");
316 return -1;
317 }
318
319
320 /* Returns the main stack size on this platform,
321 using getrlimit or a fixed size.
322 GrP fixme 64-bit? */
default_stack_size(void)323 static vki_size_t default_stack_size(void)
324 {
325 struct vki_rlimit lim;
326 int err = VG_(getrlimit)(VKI_RLIMIT_STACK, &lim);
327 if (err) return 8*1024*1024; // 8 MB
328 else return lim.rlim_cur;
329 }
330
331
332 /*
333 Processes a LC_UNIXTHREAD command.
334 Returns 0 on success, -1 on any failure.
335 The stack is mapped in and returned in *out_stack.
336 The thread's entry point is returned in *out_entry.
337 */
338 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)339 load_unixthread(vki_uint8_t **out_stack_start, vki_uint8_t **out_stack_end,
340 vki_uint8_t **out_entry, struct thread_command *threadcmd)
341 {
342 int err;
343 vki_uint8_t *stack_end;
344 int customstack;
345
346 err = load_genericthread(&stack_end, &customstack, out_entry, threadcmd);
347 if (err) return -1;
348
349 if (!stack_end) {
350 print("bad executable (no thread stack)\n");
351 return -1;
352 }
353
354 if (!customstack) {
355 // Map the stack
356 vki_size_t stacksize = VG_PGROUNDUP(default_stack_size());
357 vm_address_t stackbase = VG_PGROUNDDN(stack_end-stacksize);
358 SysRes res;
359
360 res = VG_(am_mmap_anon_fixed_client)(stackbase, stacksize, VKI_PROT_READ|VKI_PROT_WRITE|VKI_PROT_EXEC);
361 check_mmap(res, stackbase, stacksize, "load_unixthread1");
362 if (out_stack_start) *out_stack_start = (vki_uint8_t *)stackbase;
363 } else {
364 // custom stack - mapped via __UNIXTHREAD segment
365 }
366
367 if (out_stack_end) *out_stack_end = stack_end;
368
369 return 0;
370 }
371
372
373 /*
374 Processes an LC_LOAD_DYLINKER command.
375 Returns 0 on success, -1 on any error.
376 The linker itself is mapped into memory.
377 The linker's entry point is returned in *linker_entry.
378 */
379 static int
load_dylinker(vki_uint8_t ** linker_entry,struct dylinker_command * dycmd)380 load_dylinker(vki_uint8_t **linker_entry, struct dylinker_command *dycmd)
381 {
382 const char *name;
383
384 if (dycmd->name.offset >= dycmd->cmdsize) {
385 print("bad executable (invalid dylinker command)\n");
386 return -1;
387 }
388
389 name = dycmd->name.offset + (char *)dycmd;
390
391 // GrP fixme assumes name is terminated somewhere
392 return open_dylinker(name, linker_entry);
393 }
394
395
396 /*
397 Process an LC_THREAD command.
398 Returns 0 on success, -1 on any failure.
399 The thread's entry point is returned in *out_entry.
400 */
401 static int
load_thread(vki_uint8_t ** out_entry,struct thread_command * threadcmd)402 load_thread(vki_uint8_t **out_entry, struct thread_command *threadcmd)
403 {
404 int customstack;
405 int err;
406
407 err = load_genericthread(NULL, &customstack, out_entry, threadcmd);
408 if (err) return -1;
409 if (customstack) {
410 print("bad executable (stackless thread has stack)\n");
411 return -1;
412 }
413 return 0;
414 }
415
416
417 /*
418 Loads a Mach-O executable into memory, along with any threads,
419 stacks, and dylinker.
420 Returns 0 on success, -1 on any failure.
421 fd[offset..offset+size) is a Mach-O thin file.
422 filetype is MH_EXECUTE or MH_DYLINKER.
423 The mapped but empty stack is returned in *out_stack.
424 The executable's Mach headers are returned in *out_text.
425 The executable's entry point is returned in *out_entry.
426 The dylinker's entry point (if any) is returned in *out_linker_entry.
427 GrP fixme need to return whether dylinker was found - stack layout is different
428 */
429 static int
load_thin_file(int fd,vki_off_t offset,vki_off_t size,unsigned long filetype,const char * 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)430 load_thin_file(int fd, vki_off_t offset, vki_off_t size, unsigned long filetype,
431 const char *filename,
432 vki_uint8_t **out_stack_start, vki_uint8_t **out_stack_end,
433 vki_uint8_t **out_text, vki_uint8_t **out_entry, vki_uint8_t **out_linker_entry)
434 {
435 struct MACH_HEADER mh;
436 vki_uint8_t *headers;
437 vki_uint8_t *headers_end;
438 struct load_command *lc;
439 struct load_command *lcend;
440 struct SEGMENT_COMMAND *segcmd;
441 struct thread_command *threadcmd;
442 struct dylinker_command *dycmd;
443 int err;
444 SysRes res;
445 vki_size_t len;
446
447 vki_uint8_t *stack_start = NULL; // allocated thread stack (hot end)
448 vki_uint8_t *stack_end = NULL; // allocated thread stack (cold end)
449 vki_uint8_t *entry = NULL; // static entry point
450 vki_uint8_t *text = NULL; // start of text segment (i.e. the mach headers)
451 vki_uint8_t *linker_entry = NULL; // dylinker entry point
452
453 // Read Mach-O header
454 if (sizeof(mh) > size) {
455 print("bad executable (no Mach-O header)\n");
456 }
457 res = VG_(pread)(fd, &mh, sizeof(mh), offset);
458 if (sr_isError(res) || sr_Res(res) != sizeof(mh)) {
459 print("bad executable (no Mach-O header)\n");
460 return -1;
461 }
462
463
464 // Sanity-check the header itself
465 if (mh.magic != MAGIC) {
466 print("bad executable (no Mach-O magic)\n");
467 return -1;
468 }
469
470 if (mh.filetype != filetype) {
471 // expecting MH_EXECUTE or MH_DYLINKER
472 print("bad executable (wrong file type)\n");
473 return -1;
474 }
475
476
477 // Map all headers into memory
478 len = sizeof(mh) + mh.sizeofcmds;
479 if (len > size) {
480 print("bad executable (missing load commands)\n");
481 return -1;
482 }
483
484 headers = VG_(malloc)("ume.macho.headers", len);
485 res = VG_(pread)(fd, headers, len, offset);
486 if (sr_isError(res)) {
487 print("couldn't read load commands from executable\n");
488 return -1;
489 }
490 headers_end = headers + size;
491
492
493 // Map some segments into client memory:
494 // LC_SEGMENT (text, data, etc)
495 // UNIXSTACK (stack)
496 // LOAD_DYLINKER (dyld)
497 lcend = (struct load_command *)(headers + mh.sizeofcmds + sizeof(mh));
498 for (lc = (struct load_command *)(headers + sizeof(mh));
499 lc < lcend;
500 lc = (struct load_command *)(lc->cmdsize + (vki_uint8_t *)lc))
501 {
502 if ((vki_uint8_t *)lc < headers ||
503 lc->cmdsize+(vki_uint8_t *)lc > headers_end) {
504 print("bad executable (invalid load commands)\n");
505 return -1;
506 }
507
508 switch (lc->cmd) {
509 case LC_SEGMENT_CMD:
510 if (lc->cmdsize < sizeof(struct SEGMENT_COMMAND)) {
511 print("bad executable (invalid load commands)\n");
512 return -1;
513 }
514 segcmd = (struct SEGMENT_COMMAND *)lc;
515 err = load_segment(fd, offset, size, &text, &stack_start,
516 segcmd, filename);
517 if (err) return -1;
518
519 break;
520
521 case LC_UNIXTHREAD:
522 if (stack_end || entry) {
523 print("bad executable (multiple thread commands)\n");
524 return -1;
525 }
526 if (lc->cmdsize < sizeof(struct thread_command)) {
527 print("bad executable (invalid load commands)\n");
528 return -1;
529 }
530 threadcmd = (struct thread_command *)lc;
531 err = load_unixthread(&stack_start, &stack_end, &entry, threadcmd);
532 if (err) return -1;
533 break;
534
535 case LC_LOAD_DYLINKER:
536 if (filetype == MH_DYLINKER) {
537 print("bad executable (dylinker needs a dylinker)\n");
538 return -1;
539 }
540 if (linker_entry) {
541 print("bad executable (multiple dylinker commands)\n");
542 }
543 if (lc->cmdsize < sizeof(struct dylinker_command)) {
544 print("bad executable (invalid load commands)\n");
545 return -1;
546 }
547 dycmd = (struct dylinker_command *)lc;
548 err = load_dylinker(&linker_entry, dycmd);
549 if (err) return -1;
550 break;
551
552 case LC_THREAD:
553 if (filetype == MH_EXECUTE) {
554 print("bad executable (stackless thread)\n");
555 return -1;
556 }
557 if (stack_end || entry) {
558 print("bad executable (multiple thread commands)\n");
559 return -1;
560 }
561 if (lc->cmdsize < sizeof(struct thread_command)) {
562 print("bad executable (invalid load commands)\n");
563 return -1;
564 }
565 threadcmd = (struct thread_command *)lc;
566 err = load_thread(&entry, threadcmd);
567 if (err) return -1;
568 break;
569
570 default:
571 break;
572 }
573 }
574
575
576 // Done with the headers
577 VG_(free)(headers);
578
579 if (filetype == MH_EXECUTE) {
580 // Verify the necessary pieces for an executable:
581 // a stack
582 // a text segment
583 // an entry point (static or linker)
584 if (!stack_end || !stack_start) {
585 print("bad executable (no stack)\n");
586 return -1;
587 }
588 if (!text) {
589 print("bad executable (no text segment)\n");
590 return -1;
591 }
592 if (!entry && !linker_entry) {
593 print("bad executable (no entry point)\n");
594 return -1;
595 }
596 }
597 else if (filetype == MH_DYLINKER) {
598 // Verify the necessary pieces for a dylinker:
599 // an entry point
600 if (!entry) {
601 print("bad executable (no entry point)\n");
602 return -1;
603 }
604 }
605
606 if (out_stack_start) *out_stack_start = stack_start;
607 if (out_stack_end) *out_stack_end = stack_end;
608 if (out_text) *out_text = text;
609 if (out_entry) *out_entry = entry;
610 if (out_linker_entry) *out_linker_entry = linker_entry;
611
612 return 0;
613 }
614
615
616 /*
617 Load a fat Mach-O executable.
618 */
619 static int
load_fat_file(int fd,vki_off_t offset,vki_off_t size,unsigned long filetype,const char * 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)620 load_fat_file(int fd, vki_off_t offset, vki_off_t size, unsigned long filetype,
621 const char *filename,
622 vki_uint8_t **out_stack_start, vki_uint8_t **out_stack_end,
623 vki_uint8_t **out_text, vki_uint8_t **out_entry, vki_uint8_t **out_linker_entry)
624 {
625 struct fat_header fh;
626 vki_off_t arch_offset;
627 int i;
628 cpu_type_t good_arch;
629 SysRes res;
630
631 #if defined(VGA_ppc32)
632 good_arch = CPU_TYPE_POWERPC;
633 #elif defined(VGA_ppc64)
634 good_arch = CPU_TYPE_POWERPC64;
635 #elif defined(VGA_x86)
636 good_arch = CPU_TYPE_I386;
637 #elif defined(VGA_amd64)
638 good_arch = CPU_TYPE_X86_64;
639 #else
640 # error unknown architecture
641 #endif
642
643 // Read fat header
644 // All fat contents are BIG-ENDIAN
645 if (size < sizeof(fh)) {
646 print("bad executable (bad fat header)\n");
647 return -1;
648 }
649 res = VG_(pread)(fd, &fh, sizeof(fh), offset);
650 if (sr_isError(res) || sr_Res(res) != sizeof(fh)) {
651 print("bad executable (bad fat header)\n");
652 return -1;
653 }
654
655 // Scan arch headers looking for a good one
656 arch_offset = offset + sizeof(fh);
657 fh.nfat_arch = VG_(ntohl)(fh.nfat_arch);
658 for (i = 0; i < fh.nfat_arch; i++) {
659 struct fat_arch arch;
660 if (arch_offset + sizeof(arch) > size) {
661 print("bad executable (corrupt fat archs)\n");
662 return -1;
663 }
664
665 res = VG_(pread)(fd, &arch, sizeof(arch), arch_offset);
666 arch_offset += sizeof(arch);
667 if (sr_isError(res) || sr_Res(res) != sizeof(arch)) {
668 VG_(printf)("bad executable (corrupt fat arch) %x %llu\n",
669 arch.cputype, (ULong)arch_offset);
670 return -1;
671 }
672
673 arch.cputype = VG_(ntohl)(arch.cputype);
674 arch.cpusubtype = VG_(ntohl)(arch.cpusubtype);
675 arch.offset = VG_(ntohl)(arch.offset);
676 arch.size = VG_(ntohl)(arch.size);
677 arch.align = VG_(ntohl)(arch.align);
678 if (arch.cputype == good_arch) {
679 // use this arch
680 if (arch.offset > size || arch.offset + arch.size > size) {
681 print("bad executable (corrupt fat arch 2)\n");
682 return -1;
683 }
684 return load_mach_file(fd, offset+arch.offset, arch.size, filetype,
685 filename, out_stack_start, out_stack_end,
686 out_text, out_entry, out_linker_entry);
687 }
688 }
689
690 print("bad executable (can't run on this machine)\n");
691 return -1;
692 }
693
694 /*
695 Load a Mach-O executable or dylinker.
696 The file may be fat or thin.
697 */
698 static int
load_mach_file(int fd,vki_off_t offset,vki_off_t size,unsigned long filetype,const char * 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_mach_file(int fd, vki_off_t offset, vki_off_t size, unsigned long filetype,
700 const char *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 vki_uint32_t magic;
705 SysRes res;
706
707 if (size < sizeof(magic)) {
708 print("bad executable (no Mach-O magic)\n");
709 return -1;
710 }
711 res = VG_(pread)(fd, &magic, sizeof(magic), offset);
712 if (sr_isError(res) || sr_Res(res) != sizeof(magic)) {
713 print("bad executable (no Mach-O magic)\n");
714 return -1;
715 }
716
717 if (magic == MAGIC) {
718 // thin
719 return load_thin_file(fd, offset, size, filetype, filename,
720 out_stack_start, out_stack_end,
721 out_text, out_entry, out_linker_entry);
722 } else if (magic == VG_(htonl)(FAT_MAGIC)) {
723 // fat
724 return load_fat_file(fd, offset, size, filetype, filename,
725 out_stack_start, out_stack_end,
726 out_text, out_entry, out_linker_entry);
727 } else {
728 // huh?
729 print("bad executable (bad Mach-O magic)\n");
730 return -1;
731 }
732 }
733
734
VG_(match_macho)735 Bool VG_(match_macho)(Char *hdr, Int len)
736 {
737 vki_uint32_t *magic = (vki_uint32_t *)hdr;
738
739 // GrP fixme check more carefully for matching fat arch?
740
741 return (len >= VKI_PAGE_SIZE &&
742 (*magic == MAGIC || *magic == VG_(ntohl)(FAT_MAGIC)))
743 ? True : False;
744 }
745
746
VG_(load_macho)747 Int VG_(load_macho)(Int fd, const HChar *name, ExeInfo *info)
748 {
749 int err;
750 struct vg_stat sb;
751 vki_uint8_t *stack_start;
752 vki_uint8_t *stack_end;
753 vki_uint8_t *text;
754 vki_uint8_t *entry;
755 vki_uint8_t *linker_entry;
756
757 err = VG_(fstat)(fd, &sb);
758 if (err) {
759 print("couldn't stat executable\n");
760 return VKI_ENOEXEC;
761 }
762
763 err = load_mach_file(fd, 0, sb.size, MH_EXECUTE, name,
764 &stack_start, &stack_end,
765 &text, &entry, &linker_entry);
766 if (err) return VKI_ENOEXEC;
767
768 // GrP fixme exe_base
769 // GrP fixme exe_end
770 info->entry = (Addr)entry;
771 info->init_ip = (Addr)(linker_entry ? linker_entry : entry);
772 info->brkbase = 0xffffffff; // GrP fixme hack
773 info->init_toc = 0; // GrP fixme unused
774
775 info->stack_start = (Addr)stack_start;
776 info->stack_end = (Addr)stack_end;
777 info->text = (Addr)text;
778 info->dynamic = linker_entry ? True : False;
779
780 info->executable_path = VG_(strdup)("ume.macho.executable_path", name);
781
782 return 0;
783 }
784
785 #endif // defined(VGO_darwin)
786
787 /*--------------------------------------------------------------------*/
788 /*--- end ---*/
789 /*--------------------------------------------------------------------*/
790
791