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-2011 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 71static void print(const char *str) 72{ 73 VG_(printf)("%s", str); 74} 75 76static 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 86static int 87load_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 92static int 93load_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 98static int 99load_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 */ 110static int 111open_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*/ 163static int 164load_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*/ 264static int 265load_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? */ 323static 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*/ 338static int 339load_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*/ 379static int 380load_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*/ 401static int 402load_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*/ 429static int 430load_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*/ 619static int 620load_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*/ 698static int 699load_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 735Bool 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 747Int 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