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