macho.c revision ea2d6fd6aaf98d261df9fdf580542ebf01b7fba4
1f76d27a697a7b0bf3b84490baf60623fc96a23afnjn 2f76d27a697a7b0bf3b84490baf60623fc96a23afnjn/*--------------------------------------------------------------------*/ 3f76d27a697a7b0bf3b84490baf60623fc96a23afnjn/*--- User-mode execve() for Mach-O executables m_ume_macho.c ---*/ 4f76d27a697a7b0bf3b84490baf60623fc96a23afnjn/*--------------------------------------------------------------------*/ 5f76d27a697a7b0bf3b84490baf60623fc96a23afnjn 6f76d27a697a7b0bf3b84490baf60623fc96a23afnjn/* 7f76d27a697a7b0bf3b84490baf60623fc96a23afnjn This file is part of Valgrind, a dynamic binary instrumentation 8f76d27a697a7b0bf3b84490baf60623fc96a23afnjn framework. 9f76d27a697a7b0bf3b84490baf60623fc96a23afnjn 109eecbbb9a9cbbd30b903c09a9e04d8efc20bda33sewardj Copyright (C) 2005-2010 Apple Inc. 11f76d27a697a7b0bf3b84490baf60623fc96a23afnjn Greg Parker gparker@apple.com 12f76d27a697a7b0bf3b84490baf60623fc96a23afnjn 13f76d27a697a7b0bf3b84490baf60623fc96a23afnjn This program is free software; you can redistribute it and/or 14f76d27a697a7b0bf3b84490baf60623fc96a23afnjn modify it under the terms of the GNU General Public License as 15f76d27a697a7b0bf3b84490baf60623fc96a23afnjn published by the Free Software Foundation; either version 2 of the 16f76d27a697a7b0bf3b84490baf60623fc96a23afnjn License, or (at your option) any later version. 17f76d27a697a7b0bf3b84490baf60623fc96a23afnjn 18f76d27a697a7b0bf3b84490baf60623fc96a23afnjn This program is distributed in the hope that it will be useful, but 19f76d27a697a7b0bf3b84490baf60623fc96a23afnjn WITHOUT ANY WARRANTY; without even the implied warranty of 20f76d27a697a7b0bf3b84490baf60623fc96a23afnjn MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 21f76d27a697a7b0bf3b84490baf60623fc96a23afnjn General Public License for more details. 22f76d27a697a7b0bf3b84490baf60623fc96a23afnjn 23f76d27a697a7b0bf3b84490baf60623fc96a23afnjn You should have received a copy of the GNU General Public License 24f76d27a697a7b0bf3b84490baf60623fc96a23afnjn along with this program; if not, write to the Free Software 25f76d27a697a7b0bf3b84490baf60623fc96a23afnjn Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 26f76d27a697a7b0bf3b84490baf60623fc96a23afnjn 02111-1307, USA. 27f76d27a697a7b0bf3b84490baf60623fc96a23afnjn 28f76d27a697a7b0bf3b84490baf60623fc96a23afnjn The GNU General Public License is contained in the file COPYING. 29f76d27a697a7b0bf3b84490baf60623fc96a23afnjn*/ 30f76d27a697a7b0bf3b84490baf60623fc96a23afnjn 318b68b64759254d514d98328c496cbd88cde4c9a5njn#if defined(VGO_darwin) 328b68b64759254d514d98328c496cbd88cde4c9a5njn 33f76d27a697a7b0bf3b84490baf60623fc96a23afnjn#include "pub_core_basics.h" 34f76d27a697a7b0bf3b84490baf60623fc96a23afnjn#include "pub_core_vki.h" 35f76d27a697a7b0bf3b84490baf60623fc96a23afnjn 36f76d27a697a7b0bf3b84490baf60623fc96a23afnjn#include "pub_core_aspacemgr.h" // various mapping fns 37f76d27a697a7b0bf3b84490baf60623fc96a23afnjn#include "pub_core_debuglog.h" 38f76d27a697a7b0bf3b84490baf60623fc96a23afnjn#include "pub_core_libcassert.h" // VG_(exit), vg_assert 39f76d27a697a7b0bf3b84490baf60623fc96a23afnjn#include "pub_core_libcbase.h" // VG_(memcmp), etc 40f76d27a697a7b0bf3b84490baf60623fc96a23afnjn#include "pub_core_libcfile.h" // VG_(open) et al 41f76d27a697a7b0bf3b84490baf60623fc96a23afnjn#include "pub_core_libcprint.h" 42f76d27a697a7b0bf3b84490baf60623fc96a23afnjn#include "pub_core_libcproc.h" 43f76d27a697a7b0bf3b84490baf60623fc96a23afnjn#include "pub_core_machine.h" // VG_ELF_CLASS (XXX: which should be moved) 44f76d27a697a7b0bf3b84490baf60623fc96a23afnjn#include "pub_core_mallocfree.h" // VG_(malloc), VG_(free) 45f76d27a697a7b0bf3b84490baf60623fc96a23afnjn#include "pub_core_syscall.h" // VG_(strerror) 46f76d27a697a7b0bf3b84490baf60623fc96a23afnjn#include "pub_core_ume.h" // self 47f76d27a697a7b0bf3b84490baf60623fc96a23afnjn 48f76d27a697a7b0bf3b84490baf60623fc96a23afnjn#include "priv_ume.h" 49f76d27a697a7b0bf3b84490baf60623fc96a23afnjn 50f76d27a697a7b0bf3b84490baf60623fc96a23afnjn#include <mach/mach.h> 51f76d27a697a7b0bf3b84490baf60623fc96a23afnjn 52f76d27a697a7b0bf3b84490baf60623fc96a23afnjn#include <mach-o/dyld.h> 53f76d27a697a7b0bf3b84490baf60623fc96a23afnjn#include <mach-o/fat.h> 54f76d27a697a7b0bf3b84490baf60623fc96a23afnjn#include <mach-o/loader.h> 55f76d27a697a7b0bf3b84490baf60623fc96a23afnjn 56f76d27a697a7b0bf3b84490baf60623fc96a23afnjn#if VG_WORDSIZE == 4 57f76d27a697a7b0bf3b84490baf60623fc96a23afnjn#define MAGIC MH_MAGIC 58f76d27a697a7b0bf3b84490baf60623fc96a23afnjn#define MACH_HEADER mach_header 59f76d27a697a7b0bf3b84490baf60623fc96a23afnjn#define LC_SEGMENT_CMD LC_SEGMENT 60f76d27a697a7b0bf3b84490baf60623fc96a23afnjn#define SEGMENT_COMMAND segment_command 61f76d27a697a7b0bf3b84490baf60623fc96a23afnjn#define SECTION section 62f76d27a697a7b0bf3b84490baf60623fc96a23afnjn#else 63f76d27a697a7b0bf3b84490baf60623fc96a23afnjn#define MAGIC MH_MAGIC_64 64f76d27a697a7b0bf3b84490baf60623fc96a23afnjn#define MACH_HEADER mach_header_64 65f76d27a697a7b0bf3b84490baf60623fc96a23afnjn#define LC_SEGMENT_CMD LC_SEGMENT_64 66f76d27a697a7b0bf3b84490baf60623fc96a23afnjn#define SEGMENT_COMMAND segment_command_64 67f76d27a697a7b0bf3b84490baf60623fc96a23afnjn#define SECTION section_64 68f76d27a697a7b0bf3b84490baf60623fc96a23afnjn#endif 69f76d27a697a7b0bf3b84490baf60623fc96a23afnjn 70f76d27a697a7b0bf3b84490baf60623fc96a23afnjn 71f76d27a697a7b0bf3b84490baf60623fc96a23afnjnstatic void print(const char *str) 72f76d27a697a7b0bf3b84490baf60623fc96a23afnjn{ 73f76d27a697a7b0bf3b84490baf60623fc96a23afnjn VG_(printf)("%s", str); 74f76d27a697a7b0bf3b84490baf60623fc96a23afnjn} 75f76d27a697a7b0bf3b84490baf60623fc96a23afnjn 76ea2d6fd6aaf98d261df9fdf580542ebf01b7fba4njnstatic void check_mmap(SysRes res, Addr base, SizeT len, HChar* who) 77f76d27a697a7b0bf3b84490baf60623fc96a23afnjn{ 78f76d27a697a7b0bf3b84490baf60623fc96a23afnjn if (sr_isError(res)) { 79ea2d6fd6aaf98d261df9fdf580542ebf01b7fba4njn VG_(printf)("valgrind: mmap(0x%llx, %lld) failed in UME (%s).\n", 80ea2d6fd6aaf98d261df9fdf580542ebf01b7fba4njn (ULong)base, (Long)len, who); 81f76d27a697a7b0bf3b84490baf60623fc96a23afnjn VG_(exit)(1); 82f76d27a697a7b0bf3b84490baf60623fc96a23afnjn } 83f76d27a697a7b0bf3b84490baf60623fc96a23afnjn} 84f76d27a697a7b0bf3b84490baf60623fc96a23afnjn 85f76d27a697a7b0bf3b84490baf60623fc96a23afnjn 86f76d27a697a7b0bf3b84490baf60623fc96a23afnjnstatic int 87f76d27a697a7b0bf3b84490baf60623fc96a23afnjnload_thin_file(int fd, vki_off_t offset, vki_off_t size, unsigned long filetype, 88f76d27a697a7b0bf3b84490baf60623fc96a23afnjn const char *filename, 89f76d27a697a7b0bf3b84490baf60623fc96a23afnjn vki_uint8_t **out_stack_start, vki_uint8_t **out_stack_end, 90f76d27a697a7b0bf3b84490baf60623fc96a23afnjn vki_uint8_t **out_text, vki_uint8_t **out_entry, vki_uint8_t **out_linker_entry); 91f76d27a697a7b0bf3b84490baf60623fc96a23afnjn 92f76d27a697a7b0bf3b84490baf60623fc96a23afnjnstatic int 93f76d27a697a7b0bf3b84490baf60623fc96a23afnjnload_fat_file(int fd, vki_off_t offset, vki_off_t size, unsigned long filetype, 94f76d27a697a7b0bf3b84490baf60623fc96a23afnjn const char *filename, 95f76d27a697a7b0bf3b84490baf60623fc96a23afnjn vki_uint8_t **out_stack_start, vki_uint8_t **out_stack_end, 96f76d27a697a7b0bf3b84490baf60623fc96a23afnjn vki_uint8_t **out_text, vki_uint8_t **out_entry, vki_uint8_t **out_linker_entry); 97f76d27a697a7b0bf3b84490baf60623fc96a23afnjn 98f76d27a697a7b0bf3b84490baf60623fc96a23afnjnstatic int 99f76d27a697a7b0bf3b84490baf60623fc96a23afnjnload_mach_file(int fd, vki_off_t offset, vki_off_t size, unsigned long filetype, 100f76d27a697a7b0bf3b84490baf60623fc96a23afnjn const char *filename, 101f76d27a697a7b0bf3b84490baf60623fc96a23afnjn vki_uint8_t **out_stack_start, vki_uint8_t **out_stack_end, 102f76d27a697a7b0bf3b84490baf60623fc96a23afnjn vki_uint8_t **out_text, vki_uint8_t **out_entry, vki_uint8_t **out_linker_entry); 103f76d27a697a7b0bf3b84490baf60623fc96a23afnjn 104f76d27a697a7b0bf3b84490baf60623fc96a23afnjn 105f76d27a697a7b0bf3b84490baf60623fc96a23afnjn/* Open and map a dylinker file. 106f76d27a697a7b0bf3b84490baf60623fc96a23afnjn Returns 0 on success, -1 on any failure. 107f76d27a697a7b0bf3b84490baf60623fc96a23afnjn filename must be an absolute path. 108f76d27a697a7b0bf3b84490baf60623fc96a23afnjn The dylinker's entry point is returned in *out_linker_entry. 109f76d27a697a7b0bf3b84490baf60623fc96a23afnjn */ 110f76d27a697a7b0bf3b84490baf60623fc96a23afnjnstatic int 111f76d27a697a7b0bf3b84490baf60623fc96a23afnjnopen_dylinker(const char *filename, vki_uint8_t **out_linker_entry) 112f76d27a697a7b0bf3b84490baf60623fc96a23afnjn{ 113f76d27a697a7b0bf3b84490baf60623fc96a23afnjn struct vg_stat sb; 114f76d27a697a7b0bf3b84490baf60623fc96a23afnjn vki_size_t filesize; 115f76d27a697a7b0bf3b84490baf60623fc96a23afnjn SysRes res; 116f76d27a697a7b0bf3b84490baf60623fc96a23afnjn int fd; 117f76d27a697a7b0bf3b84490baf60623fc96a23afnjn int err; 118f76d27a697a7b0bf3b84490baf60623fc96a23afnjn 119f76d27a697a7b0bf3b84490baf60623fc96a23afnjn if (filename[0] != '/') { 120f76d27a697a7b0bf3b84490baf60623fc96a23afnjn print("bad executable (dylinker name is not an absolute path)\n"); 121f76d27a697a7b0bf3b84490baf60623fc96a23afnjn return -1; 122f76d27a697a7b0bf3b84490baf60623fc96a23afnjn } 123f76d27a697a7b0bf3b84490baf60623fc96a23afnjn 124f76d27a697a7b0bf3b84490baf60623fc96a23afnjn res = VG_(open)(filename, VKI_O_RDONLY, 0); 125f76d27a697a7b0bf3b84490baf60623fc96a23afnjn fd = sr_Res(res); 126f76d27a697a7b0bf3b84490baf60623fc96a23afnjn if (sr_isError(res)) { 127f76d27a697a7b0bf3b84490baf60623fc96a23afnjn print("couldn't open dylinker: "); 128f76d27a697a7b0bf3b84490baf60623fc96a23afnjn print(filename); 129f76d27a697a7b0bf3b84490baf60623fc96a23afnjn print("\n"); 130f76d27a697a7b0bf3b84490baf60623fc96a23afnjn return -1; 131f76d27a697a7b0bf3b84490baf60623fc96a23afnjn } 132f76d27a697a7b0bf3b84490baf60623fc96a23afnjn err = VG_(fstat)(fd, &sb); 133f76d27a697a7b0bf3b84490baf60623fc96a23afnjn if (err) { 134f76d27a697a7b0bf3b84490baf60623fc96a23afnjn print("couldn't stat dylinker: "); 135f76d27a697a7b0bf3b84490baf60623fc96a23afnjn print(filename); 136f76d27a697a7b0bf3b84490baf60623fc96a23afnjn print("\n"); 137f76d27a697a7b0bf3b84490baf60623fc96a23afnjn VG_(close)(fd); 138f76d27a697a7b0bf3b84490baf60623fc96a23afnjn return -1; 139f76d27a697a7b0bf3b84490baf60623fc96a23afnjn } 140f76d27a697a7b0bf3b84490baf60623fc96a23afnjn filesize = sb.size; 141f76d27a697a7b0bf3b84490baf60623fc96a23afnjn 142f76d27a697a7b0bf3b84490baf60623fc96a23afnjn err = load_mach_file(fd, 0, filesize, MH_DYLINKER, filename, 143f76d27a697a7b0bf3b84490baf60623fc96a23afnjn NULL, NULL, NULL, out_linker_entry, NULL); 144f76d27a697a7b0bf3b84490baf60623fc96a23afnjn if (err) { 145f76d27a697a7b0bf3b84490baf60623fc96a23afnjn print("...while loading dylinker: "); 146f76d27a697a7b0bf3b84490baf60623fc96a23afnjn print(filename); 147f76d27a697a7b0bf3b84490baf60623fc96a23afnjn print("\n"); 148f76d27a697a7b0bf3b84490baf60623fc96a23afnjn } 149f76d27a697a7b0bf3b84490baf60623fc96a23afnjn VG_(close)(fd); 150f76d27a697a7b0bf3b84490baf60623fc96a23afnjn return err; 151f76d27a697a7b0bf3b84490baf60623fc96a23afnjn} 152f76d27a697a7b0bf3b84490baf60623fc96a23afnjn 153f76d27a697a7b0bf3b84490baf60623fc96a23afnjn 154f76d27a697a7b0bf3b84490baf60623fc96a23afnjn/* 155f76d27a697a7b0bf3b84490baf60623fc96a23afnjn Process an LC_SEGMENT command, mapping it into memory if appropriate. 156f76d27a697a7b0bf3b84490baf60623fc96a23afnjn fd[offset..size) is a Mach-O thin file. 157f76d27a697a7b0bf3b84490baf60623fc96a23afnjn Returns 0 on success, -1 on any failure. 158f76d27a697a7b0bf3b84490baf60623fc96a23afnjn If this segment contains the executable's Mach headers, their 159f76d27a697a7b0bf3b84490baf60623fc96a23afnjn loaded address is returned in *text. 160f76d27a697a7b0bf3b84490baf60623fc96a23afnjn If this segment is a __UNIXSTACK, its start address is returned in 161f76d27a697a7b0bf3b84490baf60623fc96a23afnjn *stack_start. 162f76d27a697a7b0bf3b84490baf60623fc96a23afnjn*/ 163f76d27a697a7b0bf3b84490baf60623fc96a23afnjnstatic int 164f76d27a697a7b0bf3b84490baf60623fc96a23afnjnload_segment(int fd, vki_off_t offset, vki_off_t size, 165f76d27a697a7b0bf3b84490baf60623fc96a23afnjn vki_uint8_t **text, vki_uint8_t **stack_start, 166f76d27a697a7b0bf3b84490baf60623fc96a23afnjn struct SEGMENT_COMMAND *segcmd, const HChar *filename) 167f76d27a697a7b0bf3b84490baf60623fc96a23afnjn{ 168f76d27a697a7b0bf3b84490baf60623fc96a23afnjn SysRes res; 169f76d27a697a7b0bf3b84490baf60623fc96a23afnjn Addr addr; 170f76d27a697a7b0bf3b84490baf60623fc96a23afnjn vki_size_t filesize; // page-aligned 171f76d27a697a7b0bf3b84490baf60623fc96a23afnjn vki_size_t vmsize; // page-aligned 172f76d27a697a7b0bf3b84490baf60623fc96a23afnjn unsigned int prot; 173f76d27a697a7b0bf3b84490baf60623fc96a23afnjn 174f76d27a697a7b0bf3b84490baf60623fc96a23afnjn // GrP fixme mark __UNIXSTACK as SF_STACK 175f76d27a697a7b0bf3b84490baf60623fc96a23afnjn 176ea2d6fd6aaf98d261df9fdf580542ebf01b7fba4njn // Don't honour the client's request to map PAGEZERO. Why not? 177ea2d6fd6aaf98d261df9fdf580542ebf01b7fba4njn // Because when the kernel loaded the valgrind tool executable, 178ea2d6fd6aaf98d261df9fdf580542ebf01b7fba4njn // it will have mapped pagezero itself. So further attempts 179ea2d6fd6aaf98d261df9fdf580542ebf01b7fba4njn // to map it when loading the client are guaranteed to fail. 180ea2d6fd6aaf98d261df9fdf580542ebf01b7fba4njn#if VG_WORDSIZE == 4 181ea2d6fd6aaf98d261df9fdf580542ebf01b7fba4njn if (segcmd->vmaddr == 0 && 0 == VG_(strcmp)(segcmd->segname, SEG_PAGEZERO)) { 182ea2d6fd6aaf98d261df9fdf580542ebf01b7fba4njn if (segcmd->vmsize != 0x1000) { 183ea2d6fd6aaf98d261df9fdf580542ebf01b7fba4njn print("bad executable (__PAGEZERO is not 4 KB)\n"); 184ea2d6fd6aaf98d261df9fdf580542ebf01b7fba4njn return -1; 185ea2d6fd6aaf98d261df9fdf580542ebf01b7fba4njn } 186ea2d6fd6aaf98d261df9fdf580542ebf01b7fba4njn return 0; 187ea2d6fd6aaf98d261df9fdf580542ebf01b7fba4njn } 188ea2d6fd6aaf98d261df9fdf580542ebf01b7fba4njn#endif 189f76d27a697a7b0bf3b84490baf60623fc96a23afnjn#if VG_WORDSIZE == 8 190f76d27a697a7b0bf3b84490baf60623fc96a23afnjn if (segcmd->vmaddr == 0 && 0 == VG_(strcmp)(segcmd->segname, SEG_PAGEZERO)) { 191f76d27a697a7b0bf3b84490baf60623fc96a23afnjn if (segcmd->vmsize != 0x100000000) { 192f76d27a697a7b0bf3b84490baf60623fc96a23afnjn print("bad executable (__PAGEZERO is not 4 GB)\n"); 193f76d27a697a7b0bf3b84490baf60623fc96a23afnjn return -1; 194f76d27a697a7b0bf3b84490baf60623fc96a23afnjn } 195f76d27a697a7b0bf3b84490baf60623fc96a23afnjn return 0; 196f76d27a697a7b0bf3b84490baf60623fc96a23afnjn } 197f76d27a697a7b0bf3b84490baf60623fc96a23afnjn#endif 198f76d27a697a7b0bf3b84490baf60623fc96a23afnjn 199f76d27a697a7b0bf3b84490baf60623fc96a23afnjn // Record the segment containing the Mach headers themselves 200f76d27a697a7b0bf3b84490baf60623fc96a23afnjn if (segcmd->fileoff == 0 && segcmd->filesize != 0) { 201f76d27a697a7b0bf3b84490baf60623fc96a23afnjn if (text) *text = (vki_uint8_t *)segcmd->vmaddr; 202f76d27a697a7b0bf3b84490baf60623fc96a23afnjn } 203f76d27a697a7b0bf3b84490baf60623fc96a23afnjn 204f76d27a697a7b0bf3b84490baf60623fc96a23afnjn // Record the __UNIXSTACK start 205f76d27a697a7b0bf3b84490baf60623fc96a23afnjn if (0 == VG_(strcmp)(segcmd->segname, SEG_UNIXSTACK)) { 206f76d27a697a7b0bf3b84490baf60623fc96a23afnjn if (stack_start) *stack_start = (vki_uint8_t *)segcmd->vmaddr; 207f76d27a697a7b0bf3b84490baf60623fc96a23afnjn } 208f76d27a697a7b0bf3b84490baf60623fc96a23afnjn 209f76d27a697a7b0bf3b84490baf60623fc96a23afnjn // Sanity-check the segment 210f76d27a697a7b0bf3b84490baf60623fc96a23afnjn if (segcmd->fileoff + segcmd->filesize > size) { 211f76d27a697a7b0bf3b84490baf60623fc96a23afnjn print("bad executable (invalid segment command)\n"); 212f76d27a697a7b0bf3b84490baf60623fc96a23afnjn return -1; 213f76d27a697a7b0bf3b84490baf60623fc96a23afnjn } 214f76d27a697a7b0bf3b84490baf60623fc96a23afnjn if (segcmd->vmsize == 0) { 215f76d27a697a7b0bf3b84490baf60623fc96a23afnjn return 0; // nothing to map - ok 216f76d27a697a7b0bf3b84490baf60623fc96a23afnjn } 217f76d27a697a7b0bf3b84490baf60623fc96a23afnjn 218f76d27a697a7b0bf3b84490baf60623fc96a23afnjn // Get desired memory protection 219f76d27a697a7b0bf3b84490baf60623fc96a23afnjn // GrP fixme need maxprot too 220f76d27a697a7b0bf3b84490baf60623fc96a23afnjn prot = (((segcmd->initprot & VM_PROT_READ) ? VKI_PROT_READ : 0) | 221f76d27a697a7b0bf3b84490baf60623fc96a23afnjn ((segcmd->initprot & VM_PROT_WRITE) ? VKI_PROT_WRITE : 0) | 222f76d27a697a7b0bf3b84490baf60623fc96a23afnjn ((segcmd->initprot & VM_PROT_EXECUTE) ? VKI_PROT_EXEC : 0)); 223f76d27a697a7b0bf3b84490baf60623fc96a23afnjn 224f76d27a697a7b0bf3b84490baf60623fc96a23afnjn // Map the segment 225f76d27a697a7b0bf3b84490baf60623fc96a23afnjn filesize = VG_PGROUNDUP(segcmd->filesize); 226f76d27a697a7b0bf3b84490baf60623fc96a23afnjn vmsize = VG_PGROUNDUP(segcmd->vmsize); 227f76d27a697a7b0bf3b84490baf60623fc96a23afnjn if (filesize > 0) { 228f76d27a697a7b0bf3b84490baf60623fc96a23afnjn addr = (Addr)segcmd->vmaddr; 229ea2d6fd6aaf98d261df9fdf580542ebf01b7fba4njn VG_(debugLog)(2, "ume", "mmap fixed (file) (%#lx, %lu)\n", addr, filesize); 230f76d27a697a7b0bf3b84490baf60623fc96a23afnjn res = VG_(am_mmap_named_file_fixed_client)(addr, filesize, prot, fd, 231f76d27a697a7b0bf3b84490baf60623fc96a23afnjn offset + segcmd->fileoff, 232f76d27a697a7b0bf3b84490baf60623fc96a23afnjn filename); 233ea2d6fd6aaf98d261df9fdf580542ebf01b7fba4njn check_mmap(res, addr, filesize, "load_segment1"); 234f76d27a697a7b0bf3b84490baf60623fc96a23afnjn } 235f76d27a697a7b0bf3b84490baf60623fc96a23afnjn 236f76d27a697a7b0bf3b84490baf60623fc96a23afnjn // Zero-fill the remainder of the segment, if any 237f76d27a697a7b0bf3b84490baf60623fc96a23afnjn if (segcmd->filesize != filesize) { 238f76d27a697a7b0bf3b84490baf60623fc96a23afnjn // non-page-aligned part 239f76d27a697a7b0bf3b84490baf60623fc96a23afnjn // GrP fixme kernel doesn't do this? 240f76d27a697a7b0bf3b84490baf60623fc96a23afnjn //bzero(segcmd->filesize+(vki_uint8_t *)addr, filesize-segcmd->filesize); 241f76d27a697a7b0bf3b84490baf60623fc96a23afnjn } 242f76d27a697a7b0bf3b84490baf60623fc96a23afnjn if (filesize != vmsize) { 243f76d27a697a7b0bf3b84490baf60623fc96a23afnjn // page-aligned part 244f76d27a697a7b0bf3b84490baf60623fc96a23afnjn SizeT length = vmsize - filesize; 245f76d27a697a7b0bf3b84490baf60623fc96a23afnjn addr = (Addr)(filesize + segcmd->vmaddr); 246ea2d6fd6aaf98d261df9fdf580542ebf01b7fba4njn VG_(debugLog)(2, "ume", "mmap fixed (anon) (%#lx, %lu)\n", addr, length); 247f76d27a697a7b0bf3b84490baf60623fc96a23afnjn res = VG_(am_mmap_anon_fixed_client)(addr, length, prot); 248ea2d6fd6aaf98d261df9fdf580542ebf01b7fba4njn check_mmap(res, addr, length, "load_segment2"); 249f76d27a697a7b0bf3b84490baf60623fc96a23afnjn } 250f76d27a697a7b0bf3b84490baf60623fc96a23afnjn 251f76d27a697a7b0bf3b84490baf60623fc96a23afnjn return 0; 252f76d27a697a7b0bf3b84490baf60623fc96a23afnjn} 253f76d27a697a7b0bf3b84490baf60623fc96a23afnjn 254f76d27a697a7b0bf3b84490baf60623fc96a23afnjn 255f76d27a697a7b0bf3b84490baf60623fc96a23afnjn/* 256f76d27a697a7b0bf3b84490baf60623fc96a23afnjn Parse a LC_THREAD or LC_UNIXTHREAD command. 257f76d27a697a7b0bf3b84490baf60623fc96a23afnjn Return 0 on success, -1 on any failure. 258f76d27a697a7b0bf3b84490baf60623fc96a23afnjn The stack address is returned in *stack. If the executable requested 259f76d27a697a7b0bf3b84490baf60623fc96a23afnjn a non-default stack address, *customstack is set to TRUE. The thread's 260f76d27a697a7b0bf3b84490baf60623fc96a23afnjn entry point is returned in *entry. 261f76d27a697a7b0bf3b84490baf60623fc96a23afnjn The stack itself (if any) is not mapped. 262f76d27a697a7b0bf3b84490baf60623fc96a23afnjn Other custom register settings are silently ignored (GrP fixme). 263f76d27a697a7b0bf3b84490baf60623fc96a23afnjn*/ 264f76d27a697a7b0bf3b84490baf60623fc96a23afnjnstatic int 265f76d27a697a7b0bf3b84490baf60623fc96a23afnjnload_genericthread(vki_uint8_t **stack_end, 266f76d27a697a7b0bf3b84490baf60623fc96a23afnjn int *customstack, vki_uint8_t **entry, 267f76d27a697a7b0bf3b84490baf60623fc96a23afnjn struct thread_command *threadcmd) 268f76d27a697a7b0bf3b84490baf60623fc96a23afnjn{ 269f76d27a697a7b0bf3b84490baf60623fc96a23afnjn unsigned int flavor; 270f76d27a697a7b0bf3b84490baf60623fc96a23afnjn unsigned int count; 271f76d27a697a7b0bf3b84490baf60623fc96a23afnjn unsigned int *p; 272f76d27a697a7b0bf3b84490baf60623fc96a23afnjn unsigned int left; 273f76d27a697a7b0bf3b84490baf60623fc96a23afnjn 274f76d27a697a7b0bf3b84490baf60623fc96a23afnjn p = (unsigned int *)(threadcmd + 1); 275f76d27a697a7b0bf3b84490baf60623fc96a23afnjn left = (threadcmd->cmdsize - sizeof(struct thread_command)) / sizeof(*p); 276f76d27a697a7b0bf3b84490baf60623fc96a23afnjn 277f76d27a697a7b0bf3b84490baf60623fc96a23afnjn while (left > 0) { 278f76d27a697a7b0bf3b84490baf60623fc96a23afnjn if (left < 2) { 279f76d27a697a7b0bf3b84490baf60623fc96a23afnjn print("bad executable (invalid thread command)\n"); 280f76d27a697a7b0bf3b84490baf60623fc96a23afnjn return -1; 281f76d27a697a7b0bf3b84490baf60623fc96a23afnjn } 282f76d27a697a7b0bf3b84490baf60623fc96a23afnjn flavor = *p++; left--; 283f76d27a697a7b0bf3b84490baf60623fc96a23afnjn count = *p++; left--; 284f76d27a697a7b0bf3b84490baf60623fc96a23afnjn 285f76d27a697a7b0bf3b84490baf60623fc96a23afnjn if (left < count) { 286f76d27a697a7b0bf3b84490baf60623fc96a23afnjn print("bad executable (invalid thread command 2)\n"); 287f76d27a697a7b0bf3b84490baf60623fc96a23afnjn return -1; 288f76d27a697a7b0bf3b84490baf60623fc96a23afnjn } 289f76d27a697a7b0bf3b84490baf60623fc96a23afnjn 290f76d27a697a7b0bf3b84490baf60623fc96a23afnjn#if defined(VGA_x86) 291f76d27a697a7b0bf3b84490baf60623fc96a23afnjn if (flavor == i386_THREAD_STATE && count == i386_THREAD_STATE_COUNT) { 292f76d27a697a7b0bf3b84490baf60623fc96a23afnjn i386_thread_state_t *state = (i386_thread_state_t *)p; 293f76d27a697a7b0bf3b84490baf60623fc96a23afnjn if (entry) *entry = (vki_uint8_t *)state->__eip; 294f76d27a697a7b0bf3b84490baf60623fc96a23afnjn if (stack_end) *stack_end = (vki_uint8_t *)(state->__esp ? state->__esp : VKI_USRSTACK); 295f76d27a697a7b0bf3b84490baf60623fc96a23afnjn if (customstack) *customstack = state->__esp; 296f76d27a697a7b0bf3b84490baf60623fc96a23afnjn return 0; 297f76d27a697a7b0bf3b84490baf60623fc96a23afnjn } 298f76d27a697a7b0bf3b84490baf60623fc96a23afnjn 299f76d27a697a7b0bf3b84490baf60623fc96a23afnjn#elif defined(VGA_amd64) 300f76d27a697a7b0bf3b84490baf60623fc96a23afnjn if (flavor == x86_THREAD_STATE64 && count == x86_THREAD_STATE64_COUNT){ 301f76d27a697a7b0bf3b84490baf60623fc96a23afnjn x86_thread_state64_t *state = (x86_thread_state64_t *)p; 302f76d27a697a7b0bf3b84490baf60623fc96a23afnjn if (entry) *entry = (vki_uint8_t *)state->__rip; 303f76d27a697a7b0bf3b84490baf60623fc96a23afnjn if (stack_end) *stack_end = (vki_uint8_t *)(state->__rsp ? state->__rsp : VKI_USRSTACK64); 304f76d27a697a7b0bf3b84490baf60623fc96a23afnjn if (customstack) *customstack = state->__rsp; 305f76d27a697a7b0bf3b84490baf60623fc96a23afnjn return 0; 306f76d27a697a7b0bf3b84490baf60623fc96a23afnjn } 307f76d27a697a7b0bf3b84490baf60623fc96a23afnjn 308f76d27a697a7b0bf3b84490baf60623fc96a23afnjn#else 309f76d27a697a7b0bf3b84490baf60623fc96a23afnjn# error unknown platform 310f76d27a697a7b0bf3b84490baf60623fc96a23afnjn#endif 311f76d27a697a7b0bf3b84490baf60623fc96a23afnjn p += count; 312f76d27a697a7b0bf3b84490baf60623fc96a23afnjn left -= count; 313f76d27a697a7b0bf3b84490baf60623fc96a23afnjn } 314f76d27a697a7b0bf3b84490baf60623fc96a23afnjn 315f76d27a697a7b0bf3b84490baf60623fc96a23afnjn print("bad executable (no arch-compatible thread state)\n"); 316f76d27a697a7b0bf3b84490baf60623fc96a23afnjn return -1; 317f76d27a697a7b0bf3b84490baf60623fc96a23afnjn} 318f76d27a697a7b0bf3b84490baf60623fc96a23afnjn 319f76d27a697a7b0bf3b84490baf60623fc96a23afnjn 320f76d27a697a7b0bf3b84490baf60623fc96a23afnjn/* Returns the main stack size on this platform, 321f76d27a697a7b0bf3b84490baf60623fc96a23afnjn using getrlimit or a fixed size. 322f76d27a697a7b0bf3b84490baf60623fc96a23afnjn GrP fixme 64-bit? */ 323f76d27a697a7b0bf3b84490baf60623fc96a23afnjnstatic vki_size_t default_stack_size(void) 324f76d27a697a7b0bf3b84490baf60623fc96a23afnjn{ 325f76d27a697a7b0bf3b84490baf60623fc96a23afnjn struct vki_rlimit lim; 326f76d27a697a7b0bf3b84490baf60623fc96a23afnjn int err = VG_(getrlimit)(VKI_RLIMIT_STACK, &lim); 327f76d27a697a7b0bf3b84490baf60623fc96a23afnjn if (err) return 8*1024*1024; // 8 MB 328f76d27a697a7b0bf3b84490baf60623fc96a23afnjn else return lim.rlim_cur; 329f76d27a697a7b0bf3b84490baf60623fc96a23afnjn} 330f76d27a697a7b0bf3b84490baf60623fc96a23afnjn 331f76d27a697a7b0bf3b84490baf60623fc96a23afnjn 332f76d27a697a7b0bf3b84490baf60623fc96a23afnjn/* 333f76d27a697a7b0bf3b84490baf60623fc96a23afnjn Processes a LC_UNIXTHREAD command. 334f76d27a697a7b0bf3b84490baf60623fc96a23afnjn Returns 0 on success, -1 on any failure. 335f76d27a697a7b0bf3b84490baf60623fc96a23afnjn The stack is mapped in and returned in *out_stack. 336f76d27a697a7b0bf3b84490baf60623fc96a23afnjn The thread's entry point is returned in *out_entry. 337f76d27a697a7b0bf3b84490baf60623fc96a23afnjn*/ 338f76d27a697a7b0bf3b84490baf60623fc96a23afnjnstatic int 339f76d27a697a7b0bf3b84490baf60623fc96a23afnjnload_unixthread(vki_uint8_t **out_stack_start, vki_uint8_t **out_stack_end, 340f76d27a697a7b0bf3b84490baf60623fc96a23afnjn vki_uint8_t **out_entry, struct thread_command *threadcmd) 341f76d27a697a7b0bf3b84490baf60623fc96a23afnjn{ 342f76d27a697a7b0bf3b84490baf60623fc96a23afnjn int err; 343f76d27a697a7b0bf3b84490baf60623fc96a23afnjn vki_uint8_t *stack_end; 344f76d27a697a7b0bf3b84490baf60623fc96a23afnjn int customstack; 345f76d27a697a7b0bf3b84490baf60623fc96a23afnjn 346f76d27a697a7b0bf3b84490baf60623fc96a23afnjn err = load_genericthread(&stack_end, &customstack, out_entry, threadcmd); 347f76d27a697a7b0bf3b84490baf60623fc96a23afnjn if (err) return -1; 348f76d27a697a7b0bf3b84490baf60623fc96a23afnjn 349f76d27a697a7b0bf3b84490baf60623fc96a23afnjn if (!stack_end) { 350f76d27a697a7b0bf3b84490baf60623fc96a23afnjn print("bad executable (no thread stack)\n"); 351f76d27a697a7b0bf3b84490baf60623fc96a23afnjn return -1; 352f76d27a697a7b0bf3b84490baf60623fc96a23afnjn } 353f76d27a697a7b0bf3b84490baf60623fc96a23afnjn 354f76d27a697a7b0bf3b84490baf60623fc96a23afnjn if (!customstack) { 355f76d27a697a7b0bf3b84490baf60623fc96a23afnjn // Map the stack 356f76d27a697a7b0bf3b84490baf60623fc96a23afnjn vki_size_t stacksize = VG_PGROUNDUP(default_stack_size()); 357f76d27a697a7b0bf3b84490baf60623fc96a23afnjn vm_address_t stackbase = VG_PGROUNDDN(stack_end-stacksize); 358f76d27a697a7b0bf3b84490baf60623fc96a23afnjn SysRes res; 359f76d27a697a7b0bf3b84490baf60623fc96a23afnjn 360f76d27a697a7b0bf3b84490baf60623fc96a23afnjn res = VG_(am_mmap_anon_fixed_client)(stackbase, stacksize, VKI_PROT_READ|VKI_PROT_WRITE|VKI_PROT_EXEC); 361ea2d6fd6aaf98d261df9fdf580542ebf01b7fba4njn check_mmap(res, stackbase, stacksize, "load_unixthread1"); 362f76d27a697a7b0bf3b84490baf60623fc96a23afnjn if (out_stack_start) *out_stack_start = (vki_uint8_t *)stackbase; 363f76d27a697a7b0bf3b84490baf60623fc96a23afnjn } else { 364f76d27a697a7b0bf3b84490baf60623fc96a23afnjn // custom stack - mapped via __UNIXTHREAD segment 365f76d27a697a7b0bf3b84490baf60623fc96a23afnjn } 366f76d27a697a7b0bf3b84490baf60623fc96a23afnjn 367f76d27a697a7b0bf3b84490baf60623fc96a23afnjn if (out_stack_end) *out_stack_end = stack_end; 368f76d27a697a7b0bf3b84490baf60623fc96a23afnjn 369f76d27a697a7b0bf3b84490baf60623fc96a23afnjn return 0; 370f76d27a697a7b0bf3b84490baf60623fc96a23afnjn} 371f76d27a697a7b0bf3b84490baf60623fc96a23afnjn 372f76d27a697a7b0bf3b84490baf60623fc96a23afnjn 373f76d27a697a7b0bf3b84490baf60623fc96a23afnjn/* 374f76d27a697a7b0bf3b84490baf60623fc96a23afnjn Processes an LC_LOAD_DYLINKER command. 375f76d27a697a7b0bf3b84490baf60623fc96a23afnjn Returns 0 on success, -1 on any error. 376f76d27a697a7b0bf3b84490baf60623fc96a23afnjn The linker itself is mapped into memory. 377f76d27a697a7b0bf3b84490baf60623fc96a23afnjn The linker's entry point is returned in *linker_entry. 378f76d27a697a7b0bf3b84490baf60623fc96a23afnjn*/ 379f76d27a697a7b0bf3b84490baf60623fc96a23afnjnstatic int 380f76d27a697a7b0bf3b84490baf60623fc96a23afnjnload_dylinker(vki_uint8_t **linker_entry, struct dylinker_command *dycmd) 381f76d27a697a7b0bf3b84490baf60623fc96a23afnjn{ 382f76d27a697a7b0bf3b84490baf60623fc96a23afnjn const char *name; 383f76d27a697a7b0bf3b84490baf60623fc96a23afnjn 384f76d27a697a7b0bf3b84490baf60623fc96a23afnjn if (dycmd->name.offset >= dycmd->cmdsize) { 385f76d27a697a7b0bf3b84490baf60623fc96a23afnjn print("bad executable (invalid dylinker command)\n"); 386f76d27a697a7b0bf3b84490baf60623fc96a23afnjn return -1; 387f76d27a697a7b0bf3b84490baf60623fc96a23afnjn } 388f76d27a697a7b0bf3b84490baf60623fc96a23afnjn 389f76d27a697a7b0bf3b84490baf60623fc96a23afnjn name = dycmd->name.offset + (char *)dycmd; 390f76d27a697a7b0bf3b84490baf60623fc96a23afnjn 391f76d27a697a7b0bf3b84490baf60623fc96a23afnjn // GrP fixme assumes name is terminated somewhere 392f76d27a697a7b0bf3b84490baf60623fc96a23afnjn return open_dylinker(name, linker_entry); 393f76d27a697a7b0bf3b84490baf60623fc96a23afnjn} 394f76d27a697a7b0bf3b84490baf60623fc96a23afnjn 395f76d27a697a7b0bf3b84490baf60623fc96a23afnjn 396f76d27a697a7b0bf3b84490baf60623fc96a23afnjn/* 397f76d27a697a7b0bf3b84490baf60623fc96a23afnjn Process an LC_THREAD command. 398f76d27a697a7b0bf3b84490baf60623fc96a23afnjn Returns 0 on success, -1 on any failure. 399f76d27a697a7b0bf3b84490baf60623fc96a23afnjn The thread's entry point is returned in *out_entry. 400f76d27a697a7b0bf3b84490baf60623fc96a23afnjn*/ 401f76d27a697a7b0bf3b84490baf60623fc96a23afnjnstatic int 402f76d27a697a7b0bf3b84490baf60623fc96a23afnjnload_thread(vki_uint8_t **out_entry, struct thread_command *threadcmd) 403f76d27a697a7b0bf3b84490baf60623fc96a23afnjn{ 404f76d27a697a7b0bf3b84490baf60623fc96a23afnjn int customstack; 405f76d27a697a7b0bf3b84490baf60623fc96a23afnjn int err; 406f76d27a697a7b0bf3b84490baf60623fc96a23afnjn 407f76d27a697a7b0bf3b84490baf60623fc96a23afnjn err = load_genericthread(NULL, &customstack, out_entry, threadcmd); 408f76d27a697a7b0bf3b84490baf60623fc96a23afnjn if (err) return -1; 409f76d27a697a7b0bf3b84490baf60623fc96a23afnjn if (customstack) { 410f76d27a697a7b0bf3b84490baf60623fc96a23afnjn print("bad executable (stackless thread has stack)\n"); 411f76d27a697a7b0bf3b84490baf60623fc96a23afnjn return -1; 412f76d27a697a7b0bf3b84490baf60623fc96a23afnjn } 413f76d27a697a7b0bf3b84490baf60623fc96a23afnjn return 0; 414f76d27a697a7b0bf3b84490baf60623fc96a23afnjn} 415f76d27a697a7b0bf3b84490baf60623fc96a23afnjn 416f76d27a697a7b0bf3b84490baf60623fc96a23afnjn 417f76d27a697a7b0bf3b84490baf60623fc96a23afnjn/* 418f76d27a697a7b0bf3b84490baf60623fc96a23afnjn Loads a Mach-O executable into memory, along with any threads, 419f76d27a697a7b0bf3b84490baf60623fc96a23afnjn stacks, and dylinker. 420f76d27a697a7b0bf3b84490baf60623fc96a23afnjn Returns 0 on success, -1 on any failure. 421f76d27a697a7b0bf3b84490baf60623fc96a23afnjn fd[offset..offset+size) is a Mach-O thin file. 422f76d27a697a7b0bf3b84490baf60623fc96a23afnjn filetype is MH_EXECUTE or MH_DYLINKER. 423f76d27a697a7b0bf3b84490baf60623fc96a23afnjn The mapped but empty stack is returned in *out_stack. 424f76d27a697a7b0bf3b84490baf60623fc96a23afnjn The executable's Mach headers are returned in *out_text. 425f76d27a697a7b0bf3b84490baf60623fc96a23afnjn The executable's entry point is returned in *out_entry. 426f76d27a697a7b0bf3b84490baf60623fc96a23afnjn The dylinker's entry point (if any) is returned in *out_linker_entry. 427f76d27a697a7b0bf3b84490baf60623fc96a23afnjn GrP fixme need to return whether dylinker was found - stack layout is different 428f76d27a697a7b0bf3b84490baf60623fc96a23afnjn*/ 429f76d27a697a7b0bf3b84490baf60623fc96a23afnjnstatic int 430f76d27a697a7b0bf3b84490baf60623fc96a23afnjnload_thin_file(int fd, vki_off_t offset, vki_off_t size, unsigned long filetype, 431f76d27a697a7b0bf3b84490baf60623fc96a23afnjn const char *filename, 432f76d27a697a7b0bf3b84490baf60623fc96a23afnjn vki_uint8_t **out_stack_start, vki_uint8_t **out_stack_end, 433f76d27a697a7b0bf3b84490baf60623fc96a23afnjn vki_uint8_t **out_text, vki_uint8_t **out_entry, vki_uint8_t **out_linker_entry) 434f76d27a697a7b0bf3b84490baf60623fc96a23afnjn{ 435f76d27a697a7b0bf3b84490baf60623fc96a23afnjn struct MACH_HEADER mh; 436f76d27a697a7b0bf3b84490baf60623fc96a23afnjn vki_uint8_t *headers; 437f76d27a697a7b0bf3b84490baf60623fc96a23afnjn vki_uint8_t *headers_end; 438f76d27a697a7b0bf3b84490baf60623fc96a23afnjn struct load_command *lc; 439f76d27a697a7b0bf3b84490baf60623fc96a23afnjn struct load_command *lcend; 440f76d27a697a7b0bf3b84490baf60623fc96a23afnjn struct SEGMENT_COMMAND *segcmd; 441f76d27a697a7b0bf3b84490baf60623fc96a23afnjn struct thread_command *threadcmd; 442f76d27a697a7b0bf3b84490baf60623fc96a23afnjn struct dylinker_command *dycmd; 443f76d27a697a7b0bf3b84490baf60623fc96a23afnjn int err; 444f76d27a697a7b0bf3b84490baf60623fc96a23afnjn SysRes res; 445f76d27a697a7b0bf3b84490baf60623fc96a23afnjn vki_size_t len; 446f76d27a697a7b0bf3b84490baf60623fc96a23afnjn 447f76d27a697a7b0bf3b84490baf60623fc96a23afnjn vki_uint8_t *stack_start = NULL; // allocated thread stack (hot end) 448f76d27a697a7b0bf3b84490baf60623fc96a23afnjn vki_uint8_t *stack_end = NULL; // allocated thread stack (cold end) 449f76d27a697a7b0bf3b84490baf60623fc96a23afnjn vki_uint8_t *entry = NULL; // static entry point 450f76d27a697a7b0bf3b84490baf60623fc96a23afnjn vki_uint8_t *text = NULL; // start of text segment (i.e. the mach headers) 451f76d27a697a7b0bf3b84490baf60623fc96a23afnjn vki_uint8_t *linker_entry = NULL; // dylinker entry point 452f76d27a697a7b0bf3b84490baf60623fc96a23afnjn 453f76d27a697a7b0bf3b84490baf60623fc96a23afnjn // Read Mach-O header 454f76d27a697a7b0bf3b84490baf60623fc96a23afnjn if (sizeof(mh) > size) { 455f76d27a697a7b0bf3b84490baf60623fc96a23afnjn print("bad executable (no Mach-O header)\n"); 456f76d27a697a7b0bf3b84490baf60623fc96a23afnjn } 457f76d27a697a7b0bf3b84490baf60623fc96a23afnjn res = VG_(pread)(fd, &mh, sizeof(mh), offset); 458f76d27a697a7b0bf3b84490baf60623fc96a23afnjn if (sr_isError(res) || sr_Res(res) != sizeof(mh)) { 459f76d27a697a7b0bf3b84490baf60623fc96a23afnjn print("bad executable (no Mach-O header)\n"); 460f76d27a697a7b0bf3b84490baf60623fc96a23afnjn return -1; 461f76d27a697a7b0bf3b84490baf60623fc96a23afnjn } 462f76d27a697a7b0bf3b84490baf60623fc96a23afnjn 463f76d27a697a7b0bf3b84490baf60623fc96a23afnjn 464f76d27a697a7b0bf3b84490baf60623fc96a23afnjn // Sanity-check the header itself 465f76d27a697a7b0bf3b84490baf60623fc96a23afnjn if (mh.magic != MAGIC) { 466f76d27a697a7b0bf3b84490baf60623fc96a23afnjn print("bad executable (no Mach-O magic)\n"); 467f76d27a697a7b0bf3b84490baf60623fc96a23afnjn return -1; 468f76d27a697a7b0bf3b84490baf60623fc96a23afnjn } 469f76d27a697a7b0bf3b84490baf60623fc96a23afnjn 470f76d27a697a7b0bf3b84490baf60623fc96a23afnjn if (mh.filetype != filetype) { 471f76d27a697a7b0bf3b84490baf60623fc96a23afnjn // expecting MH_EXECUTE or MH_DYLINKER 472f76d27a697a7b0bf3b84490baf60623fc96a23afnjn print("bad executable (wrong file type)\n"); 473f76d27a697a7b0bf3b84490baf60623fc96a23afnjn return -1; 474f76d27a697a7b0bf3b84490baf60623fc96a23afnjn } 475f76d27a697a7b0bf3b84490baf60623fc96a23afnjn 476f76d27a697a7b0bf3b84490baf60623fc96a23afnjn 477f76d27a697a7b0bf3b84490baf60623fc96a23afnjn // Map all headers into memory 478f76d27a697a7b0bf3b84490baf60623fc96a23afnjn len = sizeof(mh) + mh.sizeofcmds; 479f76d27a697a7b0bf3b84490baf60623fc96a23afnjn if (len > size) { 480f76d27a697a7b0bf3b84490baf60623fc96a23afnjn print("bad executable (missing load commands)\n"); 481f76d27a697a7b0bf3b84490baf60623fc96a23afnjn return -1; 482f76d27a697a7b0bf3b84490baf60623fc96a23afnjn } 483f76d27a697a7b0bf3b84490baf60623fc96a23afnjn 484f76d27a697a7b0bf3b84490baf60623fc96a23afnjn headers = VG_(malloc)("ume.macho.headers", len); 485f76d27a697a7b0bf3b84490baf60623fc96a23afnjn res = VG_(pread)(fd, headers, len, offset); 486f76d27a697a7b0bf3b84490baf60623fc96a23afnjn if (sr_isError(res)) { 487f76d27a697a7b0bf3b84490baf60623fc96a23afnjn print("couldn't read load commands from executable\n"); 488f76d27a697a7b0bf3b84490baf60623fc96a23afnjn return -1; 489f76d27a697a7b0bf3b84490baf60623fc96a23afnjn } 490f76d27a697a7b0bf3b84490baf60623fc96a23afnjn headers_end = headers + size; 491f76d27a697a7b0bf3b84490baf60623fc96a23afnjn 492f76d27a697a7b0bf3b84490baf60623fc96a23afnjn 493f76d27a697a7b0bf3b84490baf60623fc96a23afnjn // Map some segments into client memory: 494f76d27a697a7b0bf3b84490baf60623fc96a23afnjn // LC_SEGMENT (text, data, etc) 495f76d27a697a7b0bf3b84490baf60623fc96a23afnjn // UNIXSTACK (stack) 496f76d27a697a7b0bf3b84490baf60623fc96a23afnjn // LOAD_DYLINKER (dyld) 497f76d27a697a7b0bf3b84490baf60623fc96a23afnjn lcend = (struct load_command *)(headers + mh.sizeofcmds + sizeof(mh)); 498f76d27a697a7b0bf3b84490baf60623fc96a23afnjn for (lc = (struct load_command *)(headers + sizeof(mh)); 499f76d27a697a7b0bf3b84490baf60623fc96a23afnjn lc < lcend; 500f76d27a697a7b0bf3b84490baf60623fc96a23afnjn lc = (struct load_command *)(lc->cmdsize + (vki_uint8_t *)lc)) 501f76d27a697a7b0bf3b84490baf60623fc96a23afnjn { 502f76d27a697a7b0bf3b84490baf60623fc96a23afnjn if ((vki_uint8_t *)lc < headers || 503f76d27a697a7b0bf3b84490baf60623fc96a23afnjn lc->cmdsize+(vki_uint8_t *)lc > headers_end) { 504f76d27a697a7b0bf3b84490baf60623fc96a23afnjn print("bad executable (invalid load commands)\n"); 505f76d27a697a7b0bf3b84490baf60623fc96a23afnjn return -1; 506f76d27a697a7b0bf3b84490baf60623fc96a23afnjn } 507f76d27a697a7b0bf3b84490baf60623fc96a23afnjn 508f76d27a697a7b0bf3b84490baf60623fc96a23afnjn switch (lc->cmd) { 509f76d27a697a7b0bf3b84490baf60623fc96a23afnjn case LC_SEGMENT_CMD: 510f76d27a697a7b0bf3b84490baf60623fc96a23afnjn if (lc->cmdsize < sizeof(struct SEGMENT_COMMAND)) { 511f76d27a697a7b0bf3b84490baf60623fc96a23afnjn print("bad executable (invalid load commands)\n"); 512f76d27a697a7b0bf3b84490baf60623fc96a23afnjn return -1; 513f76d27a697a7b0bf3b84490baf60623fc96a23afnjn } 514f76d27a697a7b0bf3b84490baf60623fc96a23afnjn segcmd = (struct SEGMENT_COMMAND *)lc; 515f76d27a697a7b0bf3b84490baf60623fc96a23afnjn err = load_segment(fd, offset, size, &text, &stack_start, 516f76d27a697a7b0bf3b84490baf60623fc96a23afnjn segcmd, filename); 517f76d27a697a7b0bf3b84490baf60623fc96a23afnjn if (err) return -1; 518f76d27a697a7b0bf3b84490baf60623fc96a23afnjn 519f76d27a697a7b0bf3b84490baf60623fc96a23afnjn break; 520f76d27a697a7b0bf3b84490baf60623fc96a23afnjn 521f76d27a697a7b0bf3b84490baf60623fc96a23afnjn case LC_UNIXTHREAD: 522f76d27a697a7b0bf3b84490baf60623fc96a23afnjn if (stack_end || entry) { 523f76d27a697a7b0bf3b84490baf60623fc96a23afnjn print("bad executable (multiple thread commands)\n"); 524f76d27a697a7b0bf3b84490baf60623fc96a23afnjn return -1; 525f76d27a697a7b0bf3b84490baf60623fc96a23afnjn } 526f76d27a697a7b0bf3b84490baf60623fc96a23afnjn if (lc->cmdsize < sizeof(struct thread_command)) { 527f76d27a697a7b0bf3b84490baf60623fc96a23afnjn print("bad executable (invalid load commands)\n"); 528f76d27a697a7b0bf3b84490baf60623fc96a23afnjn return -1; 529f76d27a697a7b0bf3b84490baf60623fc96a23afnjn } 530f76d27a697a7b0bf3b84490baf60623fc96a23afnjn threadcmd = (struct thread_command *)lc; 531f76d27a697a7b0bf3b84490baf60623fc96a23afnjn err = load_unixthread(&stack_start, &stack_end, &entry, threadcmd); 532f76d27a697a7b0bf3b84490baf60623fc96a23afnjn if (err) return -1; 533f76d27a697a7b0bf3b84490baf60623fc96a23afnjn break; 534f76d27a697a7b0bf3b84490baf60623fc96a23afnjn 535f76d27a697a7b0bf3b84490baf60623fc96a23afnjn case LC_LOAD_DYLINKER: 536f76d27a697a7b0bf3b84490baf60623fc96a23afnjn if (filetype == MH_DYLINKER) { 537f76d27a697a7b0bf3b84490baf60623fc96a23afnjn print("bad executable (dylinker needs a dylinker)\n"); 538f76d27a697a7b0bf3b84490baf60623fc96a23afnjn return -1; 539f76d27a697a7b0bf3b84490baf60623fc96a23afnjn } 540f76d27a697a7b0bf3b84490baf60623fc96a23afnjn if (linker_entry) { 541f76d27a697a7b0bf3b84490baf60623fc96a23afnjn print("bad executable (multiple dylinker commands)\n"); 542f76d27a697a7b0bf3b84490baf60623fc96a23afnjn } 543f76d27a697a7b0bf3b84490baf60623fc96a23afnjn if (lc->cmdsize < sizeof(struct dylinker_command)) { 544f76d27a697a7b0bf3b84490baf60623fc96a23afnjn print("bad executable (invalid load commands)\n"); 545f76d27a697a7b0bf3b84490baf60623fc96a23afnjn return -1; 546f76d27a697a7b0bf3b84490baf60623fc96a23afnjn } 547f76d27a697a7b0bf3b84490baf60623fc96a23afnjn dycmd = (struct dylinker_command *)lc; 548f76d27a697a7b0bf3b84490baf60623fc96a23afnjn err = load_dylinker(&linker_entry, dycmd); 549f76d27a697a7b0bf3b84490baf60623fc96a23afnjn if (err) return -1; 550f76d27a697a7b0bf3b84490baf60623fc96a23afnjn break; 551f76d27a697a7b0bf3b84490baf60623fc96a23afnjn 552f76d27a697a7b0bf3b84490baf60623fc96a23afnjn case LC_THREAD: 553f76d27a697a7b0bf3b84490baf60623fc96a23afnjn if (filetype == MH_EXECUTE) { 554f76d27a697a7b0bf3b84490baf60623fc96a23afnjn print("bad executable (stackless thread)\n"); 555f76d27a697a7b0bf3b84490baf60623fc96a23afnjn return -1; 556f76d27a697a7b0bf3b84490baf60623fc96a23afnjn } 557f76d27a697a7b0bf3b84490baf60623fc96a23afnjn if (stack_end || entry) { 558f76d27a697a7b0bf3b84490baf60623fc96a23afnjn print("bad executable (multiple thread commands)\n"); 559f76d27a697a7b0bf3b84490baf60623fc96a23afnjn return -1; 560f76d27a697a7b0bf3b84490baf60623fc96a23afnjn } 561f76d27a697a7b0bf3b84490baf60623fc96a23afnjn if (lc->cmdsize < sizeof(struct thread_command)) { 562f76d27a697a7b0bf3b84490baf60623fc96a23afnjn print("bad executable (invalid load commands)\n"); 563f76d27a697a7b0bf3b84490baf60623fc96a23afnjn return -1; 564f76d27a697a7b0bf3b84490baf60623fc96a23afnjn } 565f76d27a697a7b0bf3b84490baf60623fc96a23afnjn threadcmd = (struct thread_command *)lc; 566f76d27a697a7b0bf3b84490baf60623fc96a23afnjn err = load_thread(&entry, threadcmd); 567f76d27a697a7b0bf3b84490baf60623fc96a23afnjn if (err) return -1; 568f76d27a697a7b0bf3b84490baf60623fc96a23afnjn break; 569f76d27a697a7b0bf3b84490baf60623fc96a23afnjn 570f76d27a697a7b0bf3b84490baf60623fc96a23afnjn default: 571f76d27a697a7b0bf3b84490baf60623fc96a23afnjn break; 572f76d27a697a7b0bf3b84490baf60623fc96a23afnjn } 573f76d27a697a7b0bf3b84490baf60623fc96a23afnjn } 574f76d27a697a7b0bf3b84490baf60623fc96a23afnjn 575f76d27a697a7b0bf3b84490baf60623fc96a23afnjn 576f76d27a697a7b0bf3b84490baf60623fc96a23afnjn // Done with the headers 577f76d27a697a7b0bf3b84490baf60623fc96a23afnjn VG_(free)(headers); 578f76d27a697a7b0bf3b84490baf60623fc96a23afnjn 579f76d27a697a7b0bf3b84490baf60623fc96a23afnjn if (filetype == MH_EXECUTE) { 580f76d27a697a7b0bf3b84490baf60623fc96a23afnjn // Verify the necessary pieces for an executable: 581f76d27a697a7b0bf3b84490baf60623fc96a23afnjn // a stack 582f76d27a697a7b0bf3b84490baf60623fc96a23afnjn // a text segment 583f76d27a697a7b0bf3b84490baf60623fc96a23afnjn // an entry point (static or linker) 584f76d27a697a7b0bf3b84490baf60623fc96a23afnjn if (!stack_end || !stack_start) { 585f76d27a697a7b0bf3b84490baf60623fc96a23afnjn print("bad executable (no stack)\n"); 586f76d27a697a7b0bf3b84490baf60623fc96a23afnjn return -1; 587f76d27a697a7b0bf3b84490baf60623fc96a23afnjn } 588f76d27a697a7b0bf3b84490baf60623fc96a23afnjn if (!text) { 589f76d27a697a7b0bf3b84490baf60623fc96a23afnjn print("bad executable (no text segment)\n"); 590f76d27a697a7b0bf3b84490baf60623fc96a23afnjn return -1; 591f76d27a697a7b0bf3b84490baf60623fc96a23afnjn } 592f76d27a697a7b0bf3b84490baf60623fc96a23afnjn if (!entry && !linker_entry) { 593f76d27a697a7b0bf3b84490baf60623fc96a23afnjn print("bad executable (no entry point)\n"); 594f76d27a697a7b0bf3b84490baf60623fc96a23afnjn return -1; 595f76d27a697a7b0bf3b84490baf60623fc96a23afnjn } 596f76d27a697a7b0bf3b84490baf60623fc96a23afnjn } 597f76d27a697a7b0bf3b84490baf60623fc96a23afnjn else if (filetype == MH_DYLINKER) { 598f76d27a697a7b0bf3b84490baf60623fc96a23afnjn // Verify the necessary pieces for a dylinker: 599f76d27a697a7b0bf3b84490baf60623fc96a23afnjn // an entry point 600f76d27a697a7b0bf3b84490baf60623fc96a23afnjn if (!entry) { 601f76d27a697a7b0bf3b84490baf60623fc96a23afnjn print("bad executable (no entry point)\n"); 602f76d27a697a7b0bf3b84490baf60623fc96a23afnjn return -1; 603f76d27a697a7b0bf3b84490baf60623fc96a23afnjn } 604f76d27a697a7b0bf3b84490baf60623fc96a23afnjn } 605f76d27a697a7b0bf3b84490baf60623fc96a23afnjn 606f76d27a697a7b0bf3b84490baf60623fc96a23afnjn if (out_stack_start) *out_stack_start = stack_start; 607f76d27a697a7b0bf3b84490baf60623fc96a23afnjn if (out_stack_end) *out_stack_end = stack_end; 608f76d27a697a7b0bf3b84490baf60623fc96a23afnjn if (out_text) *out_text = text; 609f76d27a697a7b0bf3b84490baf60623fc96a23afnjn if (out_entry) *out_entry = entry; 610f76d27a697a7b0bf3b84490baf60623fc96a23afnjn if (out_linker_entry) *out_linker_entry = linker_entry; 611f76d27a697a7b0bf3b84490baf60623fc96a23afnjn 612f76d27a697a7b0bf3b84490baf60623fc96a23afnjn return 0; 613f76d27a697a7b0bf3b84490baf60623fc96a23afnjn} 614f76d27a697a7b0bf3b84490baf60623fc96a23afnjn 615f76d27a697a7b0bf3b84490baf60623fc96a23afnjn 616f76d27a697a7b0bf3b84490baf60623fc96a23afnjn/* 617f76d27a697a7b0bf3b84490baf60623fc96a23afnjn Load a fat Mach-O executable. 618f76d27a697a7b0bf3b84490baf60623fc96a23afnjn*/ 619f76d27a697a7b0bf3b84490baf60623fc96a23afnjnstatic int 620f76d27a697a7b0bf3b84490baf60623fc96a23afnjnload_fat_file(int fd, vki_off_t offset, vki_off_t size, unsigned long filetype, 621f76d27a697a7b0bf3b84490baf60623fc96a23afnjn const char *filename, 622f76d27a697a7b0bf3b84490baf60623fc96a23afnjn vki_uint8_t **out_stack_start, vki_uint8_t **out_stack_end, 623f76d27a697a7b0bf3b84490baf60623fc96a23afnjn vki_uint8_t **out_text, vki_uint8_t **out_entry, vki_uint8_t **out_linker_entry) 624f76d27a697a7b0bf3b84490baf60623fc96a23afnjn{ 625f76d27a697a7b0bf3b84490baf60623fc96a23afnjn struct fat_header fh; 626f76d27a697a7b0bf3b84490baf60623fc96a23afnjn vki_off_t arch_offset; 627f76d27a697a7b0bf3b84490baf60623fc96a23afnjn int i; 628f76d27a697a7b0bf3b84490baf60623fc96a23afnjn cpu_type_t good_arch; 629f76d27a697a7b0bf3b84490baf60623fc96a23afnjn SysRes res; 630f76d27a697a7b0bf3b84490baf60623fc96a23afnjn 631f76d27a697a7b0bf3b84490baf60623fc96a23afnjn#if defined(VGA_ppc32) 632f76d27a697a7b0bf3b84490baf60623fc96a23afnjn good_arch = CPU_TYPE_POWERPC; 633f76d27a697a7b0bf3b84490baf60623fc96a23afnjn#elif defined(VGA_ppc64) 634f76d27a697a7b0bf3b84490baf60623fc96a23afnjn good_arch = CPU_TYPE_POWERPC64; 635f76d27a697a7b0bf3b84490baf60623fc96a23afnjn#elif defined(VGA_x86) 636f76d27a697a7b0bf3b84490baf60623fc96a23afnjn good_arch = CPU_TYPE_I386; 637f76d27a697a7b0bf3b84490baf60623fc96a23afnjn#elif defined(VGA_amd64) 638f76d27a697a7b0bf3b84490baf60623fc96a23afnjn good_arch = CPU_TYPE_X86_64; 639f76d27a697a7b0bf3b84490baf60623fc96a23afnjn#else 640f76d27a697a7b0bf3b84490baf60623fc96a23afnjn# error unknown architecture 641f76d27a697a7b0bf3b84490baf60623fc96a23afnjn#endif 642f76d27a697a7b0bf3b84490baf60623fc96a23afnjn 643f76d27a697a7b0bf3b84490baf60623fc96a23afnjn // Read fat header 644f76d27a697a7b0bf3b84490baf60623fc96a23afnjn // All fat contents are BIG-ENDIAN 645f76d27a697a7b0bf3b84490baf60623fc96a23afnjn if (size < sizeof(fh)) { 646f76d27a697a7b0bf3b84490baf60623fc96a23afnjn print("bad executable (bad fat header)\n"); 647f76d27a697a7b0bf3b84490baf60623fc96a23afnjn return -1; 648f76d27a697a7b0bf3b84490baf60623fc96a23afnjn } 649f76d27a697a7b0bf3b84490baf60623fc96a23afnjn res = VG_(pread)(fd, &fh, sizeof(fh), offset); 650f76d27a697a7b0bf3b84490baf60623fc96a23afnjn if (sr_isError(res) || sr_Res(res) != sizeof(fh)) { 651f76d27a697a7b0bf3b84490baf60623fc96a23afnjn print("bad executable (bad fat header)\n"); 652f76d27a697a7b0bf3b84490baf60623fc96a23afnjn return -1; 653f76d27a697a7b0bf3b84490baf60623fc96a23afnjn } 654f76d27a697a7b0bf3b84490baf60623fc96a23afnjn 655f76d27a697a7b0bf3b84490baf60623fc96a23afnjn // Scan arch headers looking for a good one 656f76d27a697a7b0bf3b84490baf60623fc96a23afnjn arch_offset = offset + sizeof(fh); 657f76d27a697a7b0bf3b84490baf60623fc96a23afnjn fh.nfat_arch = VG_(ntohl)(fh.nfat_arch); 658f76d27a697a7b0bf3b84490baf60623fc96a23afnjn for (i = 0; i < fh.nfat_arch; i++) { 659f76d27a697a7b0bf3b84490baf60623fc96a23afnjn struct fat_arch arch; 660f76d27a697a7b0bf3b84490baf60623fc96a23afnjn if (arch_offset + sizeof(arch) > size) { 661f76d27a697a7b0bf3b84490baf60623fc96a23afnjn print("bad executable (corrupt fat archs)\n"); 662f76d27a697a7b0bf3b84490baf60623fc96a23afnjn return -1; 663f76d27a697a7b0bf3b84490baf60623fc96a23afnjn } 664f76d27a697a7b0bf3b84490baf60623fc96a23afnjn 665f76d27a697a7b0bf3b84490baf60623fc96a23afnjn res = VG_(pread)(fd, &arch, sizeof(arch), arch_offset); 666f76d27a697a7b0bf3b84490baf60623fc96a23afnjn arch_offset += sizeof(arch); 667f76d27a697a7b0bf3b84490baf60623fc96a23afnjn if (sr_isError(res) || sr_Res(res) != sizeof(arch)) { 668f76d27a697a7b0bf3b84490baf60623fc96a23afnjn VG_(printf)("bad executable (corrupt fat arch) %x %llu\n", 669f76d27a697a7b0bf3b84490baf60623fc96a23afnjn arch.cputype, (ULong)arch_offset); 670f76d27a697a7b0bf3b84490baf60623fc96a23afnjn return -1; 671f76d27a697a7b0bf3b84490baf60623fc96a23afnjn } 672f76d27a697a7b0bf3b84490baf60623fc96a23afnjn 673f76d27a697a7b0bf3b84490baf60623fc96a23afnjn arch.cputype = VG_(ntohl)(arch.cputype); 674f76d27a697a7b0bf3b84490baf60623fc96a23afnjn arch.cpusubtype = VG_(ntohl)(arch.cpusubtype); 675f76d27a697a7b0bf3b84490baf60623fc96a23afnjn arch.offset = VG_(ntohl)(arch.offset); 676f76d27a697a7b0bf3b84490baf60623fc96a23afnjn arch.size = VG_(ntohl)(arch.size); 677f76d27a697a7b0bf3b84490baf60623fc96a23afnjn arch.align = VG_(ntohl)(arch.align); 678f76d27a697a7b0bf3b84490baf60623fc96a23afnjn if (arch.cputype == good_arch) { 679f76d27a697a7b0bf3b84490baf60623fc96a23afnjn // use this arch 680f76d27a697a7b0bf3b84490baf60623fc96a23afnjn if (arch.offset > size || arch.offset + arch.size > size) { 681f76d27a697a7b0bf3b84490baf60623fc96a23afnjn print("bad executable (corrupt fat arch 2)\n"); 682f76d27a697a7b0bf3b84490baf60623fc96a23afnjn return -1; 683f76d27a697a7b0bf3b84490baf60623fc96a23afnjn } 684f76d27a697a7b0bf3b84490baf60623fc96a23afnjn return load_mach_file(fd, offset+arch.offset, arch.size, filetype, 685f76d27a697a7b0bf3b84490baf60623fc96a23afnjn filename, out_stack_start, out_stack_end, 686f76d27a697a7b0bf3b84490baf60623fc96a23afnjn out_text, out_entry, out_linker_entry); 687f76d27a697a7b0bf3b84490baf60623fc96a23afnjn } 688f76d27a697a7b0bf3b84490baf60623fc96a23afnjn } 689f76d27a697a7b0bf3b84490baf60623fc96a23afnjn 690f76d27a697a7b0bf3b84490baf60623fc96a23afnjn print("bad executable (can't run on this machine)\n"); 691f76d27a697a7b0bf3b84490baf60623fc96a23afnjn return -1; 692f76d27a697a7b0bf3b84490baf60623fc96a23afnjn} 693f76d27a697a7b0bf3b84490baf60623fc96a23afnjn 694f76d27a697a7b0bf3b84490baf60623fc96a23afnjn/* 695f76d27a697a7b0bf3b84490baf60623fc96a23afnjn Load a Mach-O executable or dylinker. 696f76d27a697a7b0bf3b84490baf60623fc96a23afnjn The file may be fat or thin. 697f76d27a697a7b0bf3b84490baf60623fc96a23afnjn*/ 698f76d27a697a7b0bf3b84490baf60623fc96a23afnjnstatic int 699f76d27a697a7b0bf3b84490baf60623fc96a23afnjnload_mach_file(int fd, vki_off_t offset, vki_off_t size, unsigned long filetype, 700f76d27a697a7b0bf3b84490baf60623fc96a23afnjn const char *filename, 701f76d27a697a7b0bf3b84490baf60623fc96a23afnjn vki_uint8_t **out_stack_start, vki_uint8_t **out_stack_end, 702f76d27a697a7b0bf3b84490baf60623fc96a23afnjn vki_uint8_t **out_text, vki_uint8_t **out_entry, vki_uint8_t **out_linker_entry) 703f76d27a697a7b0bf3b84490baf60623fc96a23afnjn{ 704f76d27a697a7b0bf3b84490baf60623fc96a23afnjn vki_uint32_t magic; 705f76d27a697a7b0bf3b84490baf60623fc96a23afnjn SysRes res; 706f76d27a697a7b0bf3b84490baf60623fc96a23afnjn 707f76d27a697a7b0bf3b84490baf60623fc96a23afnjn if (size < sizeof(magic)) { 708f76d27a697a7b0bf3b84490baf60623fc96a23afnjn print("bad executable (no Mach-O magic)\n"); 709f76d27a697a7b0bf3b84490baf60623fc96a23afnjn return -1; 710f76d27a697a7b0bf3b84490baf60623fc96a23afnjn } 711f76d27a697a7b0bf3b84490baf60623fc96a23afnjn res = VG_(pread)(fd, &magic, sizeof(magic), offset); 712f76d27a697a7b0bf3b84490baf60623fc96a23afnjn if (sr_isError(res) || sr_Res(res) != sizeof(magic)) { 713f76d27a697a7b0bf3b84490baf60623fc96a23afnjn print("bad executable (no Mach-O magic)\n"); 714f76d27a697a7b0bf3b84490baf60623fc96a23afnjn return -1; 715f76d27a697a7b0bf3b84490baf60623fc96a23afnjn } 716f76d27a697a7b0bf3b84490baf60623fc96a23afnjn 717f76d27a697a7b0bf3b84490baf60623fc96a23afnjn if (magic == MAGIC) { 718f76d27a697a7b0bf3b84490baf60623fc96a23afnjn // thin 719f76d27a697a7b0bf3b84490baf60623fc96a23afnjn return load_thin_file(fd, offset, size, filetype, filename, 720f76d27a697a7b0bf3b84490baf60623fc96a23afnjn out_stack_start, out_stack_end, 721f76d27a697a7b0bf3b84490baf60623fc96a23afnjn out_text, out_entry, out_linker_entry); 722f76d27a697a7b0bf3b84490baf60623fc96a23afnjn } else if (magic == VG_(htonl)(FAT_MAGIC)) { 723f76d27a697a7b0bf3b84490baf60623fc96a23afnjn // fat 724f76d27a697a7b0bf3b84490baf60623fc96a23afnjn return load_fat_file(fd, offset, size, filetype, filename, 725f76d27a697a7b0bf3b84490baf60623fc96a23afnjn out_stack_start, out_stack_end, 726f76d27a697a7b0bf3b84490baf60623fc96a23afnjn out_text, out_entry, out_linker_entry); 727f76d27a697a7b0bf3b84490baf60623fc96a23afnjn } else { 728f76d27a697a7b0bf3b84490baf60623fc96a23afnjn // huh? 729f76d27a697a7b0bf3b84490baf60623fc96a23afnjn print("bad executable (bad Mach-O magic)\n"); 730f76d27a697a7b0bf3b84490baf60623fc96a23afnjn return -1; 731f76d27a697a7b0bf3b84490baf60623fc96a23afnjn } 732f76d27a697a7b0bf3b84490baf60623fc96a23afnjn} 733f76d27a697a7b0bf3b84490baf60623fc96a23afnjn 734f76d27a697a7b0bf3b84490baf60623fc96a23afnjn 735f76d27a697a7b0bf3b84490baf60623fc96a23afnjnBool VG_(match_macho)(Char *hdr, Int len) 736f76d27a697a7b0bf3b84490baf60623fc96a23afnjn{ 737f76d27a697a7b0bf3b84490baf60623fc96a23afnjn vki_uint32_t *magic = (vki_uint32_t *)hdr; 738f76d27a697a7b0bf3b84490baf60623fc96a23afnjn 739f76d27a697a7b0bf3b84490baf60623fc96a23afnjn // GrP fixme check more carefully for matching fat arch? 740f76d27a697a7b0bf3b84490baf60623fc96a23afnjn 741f76d27a697a7b0bf3b84490baf60623fc96a23afnjn return (len >= VKI_PAGE_SIZE && 742f76d27a697a7b0bf3b84490baf60623fc96a23afnjn (*magic == MAGIC || *magic == VG_(ntohl)(FAT_MAGIC))) 743f76d27a697a7b0bf3b84490baf60623fc96a23afnjn ? True : False; 744f76d27a697a7b0bf3b84490baf60623fc96a23afnjn} 745f76d27a697a7b0bf3b84490baf60623fc96a23afnjn 746f76d27a697a7b0bf3b84490baf60623fc96a23afnjn 747f76d27a697a7b0bf3b84490baf60623fc96a23afnjnInt VG_(load_macho)(Int fd, const HChar *name, ExeInfo *info) 748f76d27a697a7b0bf3b84490baf60623fc96a23afnjn{ 749f76d27a697a7b0bf3b84490baf60623fc96a23afnjn int err; 750f76d27a697a7b0bf3b84490baf60623fc96a23afnjn struct vg_stat sb; 751f76d27a697a7b0bf3b84490baf60623fc96a23afnjn vki_uint8_t *stack_start; 752f76d27a697a7b0bf3b84490baf60623fc96a23afnjn vki_uint8_t *stack_end; 753f76d27a697a7b0bf3b84490baf60623fc96a23afnjn vki_uint8_t *text; 754f76d27a697a7b0bf3b84490baf60623fc96a23afnjn vki_uint8_t *entry; 755f76d27a697a7b0bf3b84490baf60623fc96a23afnjn vki_uint8_t *linker_entry; 756f76d27a697a7b0bf3b84490baf60623fc96a23afnjn 757f76d27a697a7b0bf3b84490baf60623fc96a23afnjn err = VG_(fstat)(fd, &sb); 758f76d27a697a7b0bf3b84490baf60623fc96a23afnjn if (err) { 759f76d27a697a7b0bf3b84490baf60623fc96a23afnjn print("couldn't stat executable\n"); 760f76d27a697a7b0bf3b84490baf60623fc96a23afnjn return VKI_ENOEXEC; 761f76d27a697a7b0bf3b84490baf60623fc96a23afnjn } 762f76d27a697a7b0bf3b84490baf60623fc96a23afnjn 763f76d27a697a7b0bf3b84490baf60623fc96a23afnjn err = load_mach_file(fd, 0, sb.size, MH_EXECUTE, name, 764f76d27a697a7b0bf3b84490baf60623fc96a23afnjn &stack_start, &stack_end, 765f76d27a697a7b0bf3b84490baf60623fc96a23afnjn &text, &entry, &linker_entry); 766f76d27a697a7b0bf3b84490baf60623fc96a23afnjn if (err) return VKI_ENOEXEC; 767f76d27a697a7b0bf3b84490baf60623fc96a23afnjn 768f76d27a697a7b0bf3b84490baf60623fc96a23afnjn // GrP fixme exe_base 769f76d27a697a7b0bf3b84490baf60623fc96a23afnjn // GrP fixme exe_end 770f76d27a697a7b0bf3b84490baf60623fc96a23afnjn info->entry = (Addr)entry; 771f76d27a697a7b0bf3b84490baf60623fc96a23afnjn info->init_ip = (Addr)(linker_entry ? linker_entry : entry); 772f76d27a697a7b0bf3b84490baf60623fc96a23afnjn info->brkbase = 0xffffffff; // GrP fixme hack 773f76d27a697a7b0bf3b84490baf60623fc96a23afnjn info->init_toc = 0; // GrP fixme unused 774f76d27a697a7b0bf3b84490baf60623fc96a23afnjn 775f76d27a697a7b0bf3b84490baf60623fc96a23afnjn info->stack_start = (Addr)stack_start; 776f76d27a697a7b0bf3b84490baf60623fc96a23afnjn info->stack_end = (Addr)stack_end; 777f76d27a697a7b0bf3b84490baf60623fc96a23afnjn info->text = (Addr)text; 778f76d27a697a7b0bf3b84490baf60623fc96a23afnjn info->dynamic = linker_entry ? True : False; 779f76d27a697a7b0bf3b84490baf60623fc96a23afnjn 780f76d27a697a7b0bf3b84490baf60623fc96a23afnjn info->executable_path = VG_(strdup)("ume.macho.executable_path", name); 781f76d27a697a7b0bf3b84490baf60623fc96a23afnjn 782f76d27a697a7b0bf3b84490baf60623fc96a23afnjn return 0; 783f76d27a697a7b0bf3b84490baf60623fc96a23afnjn} 784f76d27a697a7b0bf3b84490baf60623fc96a23afnjn 7858b68b64759254d514d98328c496cbd88cde4c9a5njn#endif // defined(VGO_darwin) 786f76d27a697a7b0bf3b84490baf60623fc96a23afnjn 787f76d27a697a7b0bf3b84490baf60623fc96a23afnjn/*--------------------------------------------------------------------*/ 788f76d27a697a7b0bf3b84490baf60623fc96a23afnjn/*--- end ---*/ 789f76d27a697a7b0bf3b84490baf60623fc96a23afnjn/*--------------------------------------------------------------------*/ 790f76d27a697a7b0bf3b84490baf60623fc96a23afnjn 791