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