Ejemplo n.º 1
0
/* Open and map a dylinker file.
   Returns 0 on success, -1 on any failure.
   filename must be an absolute path.
   The dylinker's entry point is returned in *out_linker_entry.
 */
static int 
open_dylinker(const char *filename, vki_uint8_t **out_linker_entry)
{
   struct vg_stat sb;
   vki_size_t filesize;
   SysRes res;
   int fd;
   int err;

   if (filename[0] != '/') {
      print("bad executable (dylinker name is not an absolute path)\n");
      return -1;
   }

   res = VG_(open)(filename, VKI_O_RDONLY, 0);
   fd = sr_Res(res);
   if (sr_isError(res)) {
      print("couldn't open dylinker: ");
      print(filename);
      print("\n");
      return -1;
   }
   err = VG_(fstat)(fd, &sb);
   if (err) {
      print("couldn't stat dylinker: ");
      print(filename);
      print("\n");
      VG_(close)(fd);
      return -1;
   }
   filesize = sb.size;

   err = load_mach_file(fd, 0, filesize, MH_DYLINKER, filename, 
                        NULL, NULL, NULL, out_linker_entry, NULL);
   if (err) {
      print("...while loading dylinker: ");
      print(filename);
      print("\n");
   }
   VG_(close)(fd);
   return err;
}
Ejemplo n.º 2
0
Int VG_(load_macho)(Int fd, const HChar *name, ExeInfo *info)
{
   int err;
   struct vg_stat sb;
   vki_uint8_t *stack_start;
   vki_uint8_t *stack_end;
   vki_uint8_t *text;
   vki_uint8_t *entry;
   vki_uint8_t *linker_entry;

   err = VG_(fstat)(fd, &sb);
   if (err) {
      print("couldn't stat executable\n");
      return VKI_ENOEXEC;
   }
   
   err = load_mach_file(fd, 0, sb.size, MH_EXECUTE, name, 
                        &stack_start, &stack_end, 
                        &text, &entry, &linker_entry);
   if (err) return VKI_ENOEXEC;

   // GrP fixme exe_base
   // GrP fixme exe_end
   info->entry = (Addr)entry;
   info->init_ip = (Addr)(linker_entry ? linker_entry : entry);
   info->brkbase = 0xffffffff; // GrP fixme hack
   info->init_toc = 0; // GrP fixme unused

   info->stack_start = (Addr)stack_start;
   info->stack_end = (Addr)stack_end;
   info->text = (Addr)text;
   info->dynamic = linker_entry ? True : False;

   info->executable_path = VG_(strdup)("ume.macho.executable_path", name);

   return 0;
}
Ejemplo n.º 3
0
/*
 Load a fat Mach-O executable.
*/
static int 
load_fat_file(int fd, vki_off_t offset, vki_off_t size, unsigned long filetype, 
             const char *filename, 
             vki_uint8_t **out_stack_start, vki_uint8_t **out_stack_end, 
             vki_uint8_t **out_text, vki_uint8_t **out_entry, vki_uint8_t **out_linker_entry)
{
   struct fat_header fh;
   vki_off_t arch_offset;
   int i;
   cpu_type_t good_arch;
   SysRes res;

#if defined(VGA_ppc32)
   good_arch = CPU_TYPE_POWERPC;
#elif defined(VGA_ppc64)
   good_arch = CPU_TYPE_POWERPC64;
#elif defined(VGA_x86)
   good_arch = CPU_TYPE_I386;
#elif defined(VGA_amd64)
   good_arch = CPU_TYPE_X86_64;
#else
# error unknown architecture
#endif

   // Read fat header
   // All fat contents are BIG-ENDIAN
   if (size < sizeof(fh)) {
      print("bad executable (bad fat header)\n");
      return -1;
   }
   res = VG_(pread)(fd, &fh, sizeof(fh), offset);
   if (sr_isError(res)  ||  sr_Res(res) != sizeof(fh)) {
      print("bad executable (bad fat header)\n");
      return -1;
   }
   
   // Scan arch headers looking for a good one
   arch_offset = offset + sizeof(fh);
   fh.nfat_arch = VG_(ntohl)(fh.nfat_arch);
   for (i = 0; i < fh.nfat_arch; i++) {
      struct fat_arch arch;
      if (arch_offset + sizeof(arch) > size) {
          print("bad executable (corrupt fat archs)\n");
          return -1;
      }

      res = VG_(pread)(fd, &arch, sizeof(arch), arch_offset);
      arch_offset += sizeof(arch);
      if (sr_isError(res)  ||  sr_Res(res) != sizeof(arch)) {
         VG_(printf)("bad executable (corrupt fat arch) %x %llu\n", 
                     arch.cputype, (ULong)arch_offset);
         return -1;
      }

      arch.cputype = VG_(ntohl)(arch.cputype);
      arch.cpusubtype = VG_(ntohl)(arch.cpusubtype);
      arch.offset = VG_(ntohl)(arch.offset);
      arch.size = VG_(ntohl)(arch.size);
      arch.align = VG_(ntohl)(arch.align);
      if (arch.cputype == good_arch) {
         // use this arch
         if (arch.offset > size  ||  arch.offset + arch.size > size) {
            print("bad executable (corrupt fat arch 2)\n");
            return -1;
         }
         return load_mach_file(fd, offset+arch.offset, arch.size, filetype, 
                               filename, out_stack_start, out_stack_end, 
                               out_text, out_entry, out_linker_entry);
      }
   }

   print("bad executable (can't run on this machine)\n");
   return -1;
}
Ejemplo n.º 4
0
/*
 Load a fat Mach-O executable.
*/
static int 
load_fat_file(int fd, vki_off_t offset, vki_off_t size, unsigned long filetype, 
             const HChar *filename, 
             vki_uint8_t **out_stack_start, vki_uint8_t **out_stack_end, 
             vki_uint8_t **out_text, vki_uint8_t **out_entry, vki_uint8_t **out_linker_entry)
{
   struct fat_header fh;
   vki_off_t arch_offset;
   int i;
   cpu_type_t good_arch;
#if defined(VGA_arm)
   cpu_subtype_t highest_subtype;
#endif
   SysRes res;

#if defined(VGA_ppc32)
   good_arch = CPU_TYPE_POWERPC;
#elif defined(VGA_ppc64be)
   good_arch = CPU_TYPE_POWERPC64BE;
#elif defined(VGA_ppc64le)
   good_arch = CPU_TYPE_POWERPC64LE;
#elif defined(VGA_x86)
   good_arch = CPU_TYPE_I386;
#elif defined(VGA_amd64)
   good_arch = CPU_TYPE_X86_64;
#elif defined(VGA_arm)
   good_arch = CPU_TYPE_ARM;
   highest_subtype = CPU_SUBTYPE_ARM_V7;
#else
# error unknown architecture
#endif

   // Read fat header
   // All fat contents are BIG-ENDIAN
   if (size < sizeof(fh)) {
      print("bad executable (bad fat header)\n");
      return -1;
   }
   res = VG_(pread)(fd, &fh, sizeof(fh), offset);
   if (sr_isError(res)  ||  sr_Res(res) != sizeof(fh)) {
      print("bad executable (bad fat header)\n");
      return -1;
   }
   
   // Scan arch headers looking for a good one
   arch_offset = offset + sizeof(fh);
   fh.nfat_arch = VG_(ntohl)(fh.nfat_arch);
   for (i = 0; i < fh.nfat_arch; i++) {
      struct fat_arch arch;
      if (arch_offset + sizeof(arch) > size) {
          print("bad executable (corrupt fat archs)\n");
          return -1;
      }

      res = VG_(pread)(fd, &arch, sizeof(arch), arch_offset);
      arch_offset += sizeof(arch);
      if (sr_isError(res)  ||  sr_Res(res) != sizeof(arch)) {
         VG_(printf)("bad executable (corrupt fat arch) %x %llu\n", 
                     arch.cputype, (ULong)arch_offset);
         return -1;
      }

      arch.cputype = VG_(ntohl)(arch.cputype);
      arch.cpusubtype = VG_(ntohl)(arch.cpusubtype);
      arch.offset = VG_(ntohl)(arch.offset);
      arch.size = VG_(ntohl)(arch.size);
      arch.align = VG_(ntohl)(arch.align);

#if defined(VGA_arm)
      if ((arch.cputype == good_arch) && (arch.cpusubtype <= highest_subtype)) {
#else
      if (arch.cputype == good_arch) {
#endif
         // use this arch
         if (arch.offset > size  ||  arch.offset + arch.size > size) {
            print("bad executable (corrupt fat arch 2)\n");
            return -1;
         }
         return load_mach_file(fd, offset+arch.offset, arch.size, filetype, 
                               filename, out_stack_start, out_stack_end, 
                               out_text, out_entry, out_linker_entry);
      }
   }

   print("bad executable (can't run on this machine)\n");
   return -1;
}

/*
 Load a Mach-O executable or dylinker.
 The file may be fat or thin.
*/
static int 
load_mach_file(int fd, vki_off_t offset, vki_off_t size, unsigned long filetype, 
              const HChar *filename, 
              vki_uint8_t **out_stack_start, vki_uint8_t **out_stack_end, 
              vki_uint8_t **out_text, vki_uint8_t **out_entry, vki_uint8_t **out_linker_entry)
{
   vki_uint32_t magic;
   SysRes res;

   if (size < sizeof(magic)) {
      print("bad executable (no Mach-O magic)\n");
      return -1;
   }
   res = VG_(pread)(fd, &magic, sizeof(magic), offset);
   if (sr_isError(res)  ||  sr_Res(res) != sizeof(magic)) {
      print("bad executable (no Mach-O magic)\n");
      return -1;
   }
   
   if (magic == MAGIC) {
      // thin
      return load_thin_file(fd, offset, size, filetype, filename, 
                            out_stack_start, out_stack_end, 
                            out_text, out_entry, out_linker_entry);
   } else if (magic == VG_(htonl)(FAT_MAGIC)) {
      // fat
      return load_fat_file(fd, offset, size, filetype, filename, 
                           out_stack_start, out_stack_end, 
                           out_text, out_entry, out_linker_entry);
   } else {
      // huh?
      print("bad executable (bad Mach-O magic)\n");
      return -1;
   }
}