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-2017 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 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
78 } load_info_t;
79
print(const HChar * str)80 static void print(const HChar *str)
81 {
82 VG_(printf)("%s", str);
83 }
84
check_mmap(SysRes res,Addr base,SizeT len,const HChar * who)85 static void check_mmap(SysRes res, Addr base, SizeT len, const HChar* who)
86 {
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)) );
92 VG_(exit)(1);
93 }
94 }
95
96 #if DARWIN_VERS >= DARWIN_10_8
check_mmap_float(SysRes res,SizeT len,const HChar * who)97 static void check_mmap_float(SysRes res, SizeT len, const HChar* who)
98 {
99 if (sr_isError(res)) {
100 VG_(printf)("valgrind: mmap-FLOAT(size=%lld) failed in UME (%s) "
101 "with error %lu (%s).\n",
102 (Long)len, who,
103 sr_Err(res), VG_(strerror)(sr_Err(res)) );
104 VG_(exit)(1);
105 }
106 }
107 #endif
108
109 static int
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);
112
113 static int
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);
116
117 static int
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);
120
121
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.
126 */
127 static int
open_dylinker(const HChar * filename,load_info_t * out_info)128 open_dylinker(const HChar *filename, load_info_t *out_info)
129 {
130 struct vg_stat sb;
131 vki_size_t filesize;
132 SysRes res;
133 int fd;
134 int err;
135
136 if (filename[0] != '/') {
137 print("bad executable (dylinker name is not an absolute path)\n");
138 return -1;
139 }
140
141 res = VG_(open)(filename, VKI_O_RDONLY, 0);
142 fd = sr_Res(res);
143 if (sr_isError(res)) {
144 VG_(printf)("couldn't open dylinker: %s\n", filename);
145 return -1;
146 }
147 err = VG_(fstat)(fd, &sb);
148 if (err) {
149 VG_(printf)("couldn't stat dylinker: %s\n", filename);
150 VG_(close)(fd);
151 return -1;
152 }
153 filesize = sb.size;
154
155 err = load_mach_file(fd, 0, filesize, MH_DYLINKER, filename, out_info);
156 if (err) {
157 VG_(printf)("...while loading dylinker: %s\n", filename);
158 }
159 VG_(close)(fd);
160 return err;
161 }
162
163
164 /*
165 Process an LC_SEGMENT command, mapping it into memory if appropriate.
166 fd[offset..size) is a Mach-O thin file.
167 Returns 0 on success, -1 on any failure.
168 If this segment contains the executable's Mach headers, their
169 loaded address is returned in out_info->text.
170 If this segment is a __UNIXSTACK, its start address is returned in
171 out_info->stack_start.
172 */
173 static int
load_segment(int fd,vki_off_t offset,vki_off_t size,struct SEGMENT_COMMAND * segcmd,const HChar * filename,load_info_t * out_info)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)
177 {
178 SysRes res;
179 Addr addr;
180 vki_size_t filesize; // page-aligned
181 vki_size_t vmsize; // page-aligned
182 vki_size_t vmend; // page-aligned
183 unsigned int prot;
184 Addr slided_addr = segcmd->vmaddr + out_info->linker_offset;
185
186 // GrP fixme mark __UNIXSTACK as SF_STACK
187
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.
192 #if VG_WORDSIZE == 4
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");
196 return -1;
197 }
198 return 0;
199 }
200 #endif
201 #if VG_WORDSIZE == 8
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");
205 return -1;
206 }
207 return 0;
208 }
209 #endif
210
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;
214 }
215
216 // Record the __UNIXSTACK start
217 if (0 == VG_(strcmp)(segcmd->segname, SEG_UNIXSTACK)) {
218 out_info->stack_start = (vki_uint8_t *)slided_addr;
219 }
220
221 // Sanity-check the segment
222 if (segcmd->fileoff + segcmd->filesize > size) {
223 print("bad executable (invalid segment command)\n");
224 return -1;
225 }
226
227 vmend = VG_PGROUNDUP(slided_addr + segcmd->vmsize);
228 if (vmend > out_info->max_addr) {
229 out_info->max_addr = vmend;
230 }
231
232 if (segcmd->vmsize == 0) {
233 return 0; // nothing to map - ok
234 }
235
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));
241
242 // Map the segment
243 filesize = VG_PGROUNDUP(segcmd->filesize);
244 vmsize = VG_PGROUNDUP(segcmd->vmsize);
245 if (filesize > 0) {
246 addr = slided_addr;
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,
250 filename);
251 check_mmap(res, addr, filesize, "load_segment1");
252 }
253
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);
259 }
260 if (filesize != vmsize) {
261 // page-aligned part
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");
267 }
268
269 return 0;
270 }
271
272
273 /*
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).
281 */
282 static int
load_genericthread(struct thread_command * threadcmd,int type,int * customstack,load_info_t * out_info)283 load_genericthread(struct thread_command *threadcmd, int type,
284 int *customstack, load_info_t *out_info)
285 {
286 unsigned int flavor;
287 unsigned int count;
288 unsigned int *p;
289 unsigned int left;
290
291 p = (unsigned int *)(threadcmd + 1);
292 left = (threadcmd->cmdsize - sizeof(struct thread_command)) / sizeof(*p);
293
294 while (left > 0) {
295 if (left < 2) {
296 print("bad executable (invalid thread command)\n");
297 return -1;
298 }
299 flavor = *p++; left--;
300 count = *p++; left--;
301
302 if (left < count) {
303 print("bad executable (invalid thread command 2)\n");
304 return -1;
305 }
306
307 #if defined(VGA_x86)
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--;
316 }
317 if (customstack) *customstack = state->__esp;
318 return 0;
319 }
320
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--;
330 }
331 if (customstack) *customstack = state->__rsp;
332 return 0;
333 }
334
335 #else
336 # error unknown platform
337 #endif
338 p += count;
339 left -= count;
340 }
341
342 print("bad executable (no arch-compatible thread state)\n");
343 return -1;
344 }
345
346
347 /* Returns the main stack size on this platform,
348 using getrlimit or a fixed size.
349 GrP fixme 64-bit? */
default_stack_size(void)350 static vki_size_t default_stack_size(void)
351 {
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;
356 }
357
358
359 /*
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.
364 */
365 static int
load_unixthread(struct thread_command * threadcmd,load_info_t * out_info)366 load_unixthread(struct thread_command *threadcmd, load_info_t *out_info)
367 {
368 int err;
369 int customstack;
370
371 err = load_genericthread(threadcmd, LC_UNIXTHREAD, &customstack, out_info);
372 if (err) return -1;
373
374 if (!out_info->stack_end) {
375 print("bad executable (no thread stack)\n");
376 return -1;
377 }
378
379 if (!customstack) {
380 // Map the stack
381 vki_size_t stacksize = VG_PGROUNDUP(default_stack_size());
382 vm_address_t stackbase = VG_PGROUNDDN(out_info->stack_end+1-stacksize);
383 SysRes res;
384
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;
388 } else {
389 // custom stack - mapped via __UNIXTHREAD segment
390 }
391
392 return 0;
393 }
394
395
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.
398
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
401 above zero. */
402 #if DARWIN_VERS >= DARWIN_10_8
403 static int
handle_lcmain(vki_size_t requested_size,load_info_t * out_info)404 handle_lcmain ( vki_size_t requested_size,
405 load_info_t *out_info )
406 {
407 if (requested_size == 0) {
408 requested_size = default_stack_size();
409 }
410 requested_size = VG_PGROUNDUP(requested_size);
411
412 const vki_size_t HACK = 64 * 1024 * 1024;
413 requested_size += HACK;
414
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;
421
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?
426
427 out_info->stack_start += HACK;
428
429 return 0;
430 }
431 #endif /* DARWIN_VERS >= DARWIN_10_8 */
432
433
434
435 /*
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.
440 */
441 static int
load_dylinker(struct dylinker_command * dycmd,load_info_t * out_info)442 load_dylinker(struct dylinker_command *dycmd, load_info_t *out_info)
443 {
444 const HChar *name;
445 int ret;
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;
454
455 if (dycmd->name.offset >= dycmd->cmdsize) {
456 print("bad executable (invalid dylinker command)\n");
457 return -1;
458 }
459
460 name = dycmd->name.offset + (HChar *)dycmd;
461
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;
466 }
467 out_info->max_addr = linker_info.max_addr;
468 return ret;
469 }
470
471
472 /*
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.
476 */
477 static int
load_thread(struct thread_command * threadcmd,load_info_t * out_info)478 load_thread(struct thread_command *threadcmd, load_info_t *out_info)
479 {
480 int customstack;
481 int err;
482
483 err = load_genericthread(threadcmd, LC_THREAD, &customstack, out_info);
484 if (err) return -1;
485 if (customstack) {
486 print("bad executable (stackless thread has stack)\n");
487 return -1;
488 }
489 return 0;
490 }
491
492
493 /*
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
505 */
506 static int
load_thin_file(int fd,vki_off_t offset,vki_off_t size,unsigned long filetype,const HChar * filename,load_info_t * out_info)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)
509 {
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;
519 int err;
520 SysRes res;
521 vki_size_t len;
522
523 // Read Mach-O header
524 if (sizeof(mh) > size) {
525 print("bad executable (no Mach-O header)\n");
526 }
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");
530 return -1;
531 }
532
533
534 // Sanity-check the header itself
535 if (mh.magic != MAGIC) {
536 print("bad executable (no Mach-O magic)\n");
537 return -1;
538 }
539
540 if (mh.filetype != filetype) {
541 // expecting MH_EXECUTE or MH_DYLINKER
542 print("bad executable (wrong file type)\n");
543 return -1;
544 }
545
546
547 // Map all headers into memory
548 len = sizeof(mh) + mh.sizeofcmds;
549 if (len > size) {
550 print("bad executable (missing load commands)\n");
551 return -1;
552 }
553
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");
558 return -1;
559 }
560 headers_end = headers + len;
561
562
563 // Map some segments into client memory:
564 // LC_SEGMENT (text, data, etc)
565 // UNIXSTACK (stack)
566 // LOAD_DYLINKER (dyld)
567 lcend = (struct load_command *)(headers + mh.sizeofcmds + sizeof(mh));
568 for (lc = (struct load_command *)(headers + sizeof(mh));
569 lc < lcend;
570 lc = (struct load_command *)(lc->cmdsize + (vki_uint8_t *)lc))
571 {
572 if ((vki_uint8_t *)lc < headers ||
573 lc->cmdsize+(vki_uint8_t *)lc > headers_end) {
574 print("bad executable (invalid load commands)\n");
575 return -1;
576 }
577
578 switch (lc->cmd) {
579
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)");
586 return -1;
587 }
588 err = handle_lcmain(epcmd->stacksize, out_info);
589 if (err) return -1;
590 VG_(debugLog)(2, "ume", "lc_main: created stack %p-%p\n",
591 out_info->stack_start, out_info->stack_end);
592 break;
593 }
594 # endif
595
596 case LC_SEGMENT_CMD:
597 if (lc->cmdsize < sizeof(struct SEGMENT_COMMAND)) {
598 print("bad executable (invalid load commands)\n");
599 return -1;
600 }
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;
606 }
607 # endif
608 err = load_segment(fd, offset, size, segcmd, filename, out_info);
609 if (err) return -1;
610
611 break;
612
613 case LC_UNIXTHREAD:
614 if (out_info->stack_end || out_info->entry) {
615 print("bad executable (multiple thread commands)\n");
616 return -1;
617 }
618 if (lc->cmdsize < sizeof(struct thread_command)) {
619 print("bad executable (invalid load commands)\n");
620 return -1;
621 }
622 threadcmd = (struct thread_command *)lc;
623 err = load_unixthread(threadcmd, out_info);
624 if (err) return -1;
625 break;
626
627 case LC_LOAD_DYLINKER:
628 if (filetype == MH_DYLINKER) {
629 print("bad executable (dylinker needs a dylinker)\n");
630 return -1;
631 }
632 if (out_info->linker_entry) {
633 print("bad executable (multiple dylinker commands)\n");
634 }
635 if (lc->cmdsize < sizeof(struct dylinker_command)) {
636 print("bad executable (invalid load commands)\n");
637 return -1;
638 }
639 dycmd = (struct dylinker_command *)lc;
640 err = load_dylinker(dycmd, out_info);
641 if (err) return -1;
642 break;
643
644 case LC_THREAD:
645 if (filetype == MH_EXECUTE) {
646 print("bad executable (stackless thread)\n");
647 return -1;
648 }
649 if (out_info->stack_end || out_info->entry) {
650 print("bad executable (multiple thread commands)\n");
651 return -1;
652 }
653 if (lc->cmdsize < sizeof(struct thread_command)) {
654 print("bad executable (invalid load commands)\n");
655 return -1;
656 }
657 threadcmd = (struct thread_command *)lc;
658 err = load_thread(threadcmd, out_info);
659 if (err) return -1;
660 break;
661
662 default:
663 break;
664 }
665 }
666
667
668 // Done with the headers
669 VG_(free)(headers);
670
671 if (filetype == MH_EXECUTE) {
672 // Verify the necessary pieces for an executable:
673 // a stack
674 // a text segment
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);
678 return -1;
679 }
680 if (!out_info->text) {
681 print("bad executable (no text segment)\n");
682 return -1;
683 }
684 if (!out_info->entry && !out_info->linker_entry) {
685 print("bad executable (no entry point)\n");
686 return -1;
687 }
688 }
689 else if (filetype == MH_DYLINKER) {
690 // Verify the necessary pieces for a dylinker:
691 // an entry point
692 if (!out_info->entry) {
693 print("bad executable (no entry point)\n");
694 return -1;
695 }
696 }
697
698 VG_(debugLog)(1, "ume", "load_thin_file: success: %s\n", filename);
699 return 0;
700 }
701
702
703 /*
704 Load a fat Mach-O executable.
705 */
706 static int
load_fat_file(int fd,vki_off_t offset,vki_off_t size,unsigned long filetype,const HChar * filename,load_info_t * out_info)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)
709 {
710 struct fat_header fh;
711 vki_off_t arch_offset;
712 int i;
713 cpu_type_t good_arch;
714 SysRes res;
715
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;
726 #else
727 # error unknown architecture
728 #endif
729
730 // Read fat header
731 // All fat contents are BIG-ENDIAN
732 if (size < sizeof(fh)) {
733 print("bad executable (bad fat header)\n");
734 return -1;
735 }
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");
739 return -1;
740 }
741
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");
749 return -1;
750 }
751
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);
757 return -1;
758 }
759
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) {
766 // use this arch
767 if (arch.offset > size || arch.offset + arch.size > size) {
768 print("bad executable (corrupt fat arch 2)\n");
769 return -1;
770 }
771 return load_mach_file(fd, offset+arch.offset, arch.size, filetype, filename, out_info);
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,load_info_t * out_info)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)
786 {
787 vki_uint32_t magic;
788 SysRes res;
789
790 if (size < sizeof(magic)) {
791 print("bad executable (no Mach-O magic)\n");
792 return -1;
793 }
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");
797 return -1;
798 }
799
800 if (magic == MAGIC) {
801 // thin
802 return load_thin_file(fd, offset, size, filetype, filename, out_info);
803 } else if (magic == VG_(htonl)(FAT_MAGIC)) {
804 // fat
805 return load_fat_file(fd, offset, size, filetype, filename, out_info);
806 } else {
807 // huh?
808 print("bad executable (bad Mach-O magic)\n");
809 return -1;
810 }
811 }
812
813
VG_(match_macho)814 Bool VG_(match_macho)(const void *hdr, SizeT len)
815 {
816 const vki_uint32_t *magic = hdr;
817
818 // GrP fixme check more carefully for matching fat arch?
819
820 return (len >= VKI_PAGE_SIZE &&
821 (*magic == MAGIC || *magic == VG_(ntohl)(FAT_MAGIC)))
822 ? True : False;
823 }
824
825
VG_(load_macho)826 Int VG_(load_macho)(Int fd, const HChar *name, ExeInfo *info)
827 {
828 int err;
829 struct vg_stat sb;
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;
838
839 err = VG_(fstat)(fd, &sb);
840 if (err) {
841 print("couldn't stat executable\n");
842 return VKI_ENOEXEC;
843 }
844
845 err = load_mach_file(fd, 0, sb.size, MH_EXECUTE, name, &load_info);
846 if (err) return VKI_ENOEXEC;
847
848 // GrP fixme exe_base
849 // GrP fixme exe_end
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
854
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;
859
860 info->executable_path = VG_(strdup)("ume.macho.executable_path", name);
861
862 return 0;
863 }
864
865 #endif // defined(VGO_darwin)
866
867 /*--------------------------------------------------------------------*/
868 /*--- end ---*/
869 /*--------------------------------------------------------------------*/
870
871