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