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 (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 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 80 static void print(const HChar *str) 81 { 82 VG_(printf)("%s", str); 83 } 84 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 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 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 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 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? */ 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 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 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 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 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 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 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 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 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 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