Exemplo n.º 1
0
void dump_fat_header(FILE *obj_file, int is_swap) {
  int header_size = sizeof(struct fat_header);
  int arch_size = sizeof(struct fat_arch);

  struct fat_header *header = load_bytes(obj_file, 0, header_size);
  if (is_swap) {
    swap_fat_header(header, 0);
  }

  int arch_offset = header_size;
  for (int i = 0; i < header->nfat_arch; i++) {
    struct fat_arch *arch = load_bytes(obj_file, arch_offset, arch_size);

    if (is_swap) {
      swap_fat_arch(arch, 1, 0);
    }
    
    int mach_header_offset = arch->offset;
    free(arch);
    arch_offset += arch_size;

    uint32_t magic = read_magic(obj_file, mach_header_offset);
    int is_64 = is_magic_64(magic);
    int is_swap_mach = should_swap_bytes(magic);
    dump_mach_header(obj_file, mach_header_offset, is_64, is_swap_mach);
  }
  free(header); 
}
Exemplo n.º 2
0
//--------------------------------------------------------------------------
bool macho_file_t::parse_fat_header()
{
  qlseek(li, start_offset);
  if ( qlread(li, &fheader, sizeof(fheader)) != sizeof(fheader) )
    return false;
  int code = (fheader.magic == FAT_MAGIC);
  if ( fheader.magic == FAT_CIGAM )
  {
    swap_fat_header(&fheader);
    code = 2;
  }
  if ( code == 0 || fheader.nfat_arch > 16 )
    return false;

  uint32 fsize = qlsize(li);
  uint32 archs_size = fheader.nfat_arch * sizeof(fat_arch);
  if ( sizeof(fat_header) + archs_size >= fsize )
    return false;

  fat_archs.resize(fheader.nfat_arch);

  if ( qlread(li, fat_archs.begin(), archs_size) != archs_size )
  {
    fat_archs.clear();
    return false;
  }

  for ( uint32_t i=0; i < fheader.nfat_arch; i++ )
  {
    fat_arch *parch = &fat_archs[i];
    if ( code == 2 )
      swap_fat_arch(parch);
    if ( parch->size <= sizeof(mach_header) ||
         parch->size >= fsize ||
         parch->offset < sizeof(fat_header) + archs_size ||
         parch->offset + parch->size > fsize )
    {
      fat_archs.clear();
      return false;
    }
  }
  return true;
}
Exemplo n.º 3
0
static int register_libraries(int fd, const char* build, const char* project, const char* filename, int* isMachO) {
	ssize_t res;
		
	uint32_t magic;
	
	res = read(fd, &magic, sizeof(uint32_t));
	if (res < sizeof(uint32_t)) { goto error_out; }

	if (magic == FAT_MAGIC || magic == FAT_CIGAM) {
		struct fat_header fh;
		int swap = 0;

		res = read(fd, &fh.nfat_arch, sizeof(struct fat_header) - sizeof(uint32_t));
		if (res < sizeof(uint32_t)) { goto error_out; }

		if (magic == FAT_CIGAM) {
			swap = 1;
			swap_fat_header(&fh, NXHostByteOrder());
		}
		
		int i;
		for (i = 0; i < fh.nfat_arch; ++i) {
			struct fat_arch fa;
			res = read(fd, &fa, sizeof(fa));
			if (res < sizeof(fa)) { goto error_out; }
			
			if (swap) swap_fat_arch(&fa, 1, NXHostByteOrder());
						
			off_t save = lseek(fd, 0, SEEK_CUR);
			lseek(fd, (off_t)fa.offset, SEEK_SET);

			register_mach_header(build, project, filename, &fa, fd, isMachO);
			
			lseek(fd, save, SEEK_SET);
		}
	} else {
		lseek(fd, 0, SEEK_SET);
		register_mach_header(build, project, filename, NULL, fd, isMachO);
	}
error_out:
	return 0;
}
Exemplo n.º 4
0
/**
 * \fn moa_error_t moa_read_fat_section(struct s_mach_file* ptr_mach_file)
 * \brief Read the fat section of a mach_file (fat_header + fat_arch).
 *
 * \param ptr_mach_file Pointer to mach archive.
 *
 * \return MOA_SUCCESS if all succeed, else error number.
 */
moa_error_t
moa_read_fat_section(struct s_mach_file* ptr_mach_file)
{
	if (NULL == ptr_mach_file)
		return MOA_ERR_NULLPTR;

	/// Reset file offset
	lseek(ptr_mach_file->fd, (off_t)0, SEEK_SET);

	/// Read the fat header
	const size_t mach_header_size = sizeof(ptr_mach_file->fat_section.fat_header);
	if (read(ptr_mach_file->fd, &ptr_mach_file->fat_section.fat_header, mach_header_size) != (ssize_t)mach_header_size)
		return MOA_ERR_READ_FAT_HEADER;

	/// Check if the file is actually a mach archive
	if (!moa_is_mach_archive(ptr_mach_file))
		return MOA_ERR_NOT_MACH_ARCHIVE;

	/// Get host machine byte order
	/// If intel CPU, we need to change the byte order to lil endian
	enum NXByteOrder host_byte_order = NXHostByteOrder();
	if (NX_LittleEndian == host_byte_order)
		swap_fat_header(&ptr_mach_file->fat_section.fat_header, NX_LittleEndian);
	else if (NX_UnknownByteOrder == NXHostByteOrder())
		return MOA_ERR_UNKNOW_ARCH;

	/// Read the N fat archs
	if (ptr_mach_file->fat_section.fat_archs != NULL)
		free(ptr_mach_file->fat_section.fat_archs);

	const size_t fat_arch_size = ptr_mach_file->fat_section.fat_header.nfat_arch * sizeof(*ptr_mach_file->fat_section.fat_archs);
	if (NULL == (ptr_mach_file->fat_section.fat_archs = (struct fat_arch*)malloc(fat_arch_size)))
		return MOA_ERR_READ_FAT_ARCH;

	if (read(ptr_mach_file->fd, ptr_mach_file->fat_section.fat_archs, fat_arch_size) != (ssize_t)fat_arch_size)
		return MOA_ERR_READ_FAT_ARCH;

	if (NX_LittleEndian == host_byte_order)
		swap_fat_arch(ptr_mach_file->fat_section.fat_archs, ptr_mach_file->fat_section.fat_header.nfat_arch, NX_LittleEndian);
	return MOA_SUCCESS;
}
Exemplo n.º 5
0
NXStream *NXGetStreamOnSection(const char *fileName, const char *segmentName, const char *sectionName)
{
    int             fd;
    struct stat     info;
    NXStream 	   *s = NULL;
    struct fat_header *fh;
    struct mach_header *mh;
    const struct section *sect;
    vm_offset_t mh_page, sect_page;
    unsigned long archOffset;
    unsigned int cnt = HOST_BASIC_INFO_COUNT;
    struct host_basic_info hbi;

    if (host_info(mach_host_self(), HOST_BASIC_INFO, (host_info_t)(&hbi), &cnt) != KERN_SUCCESS)
      return NULL;

    fd = open(fileName, O_RDONLY, 0444);
    if (fd < 0 || fstat(fd, &info) < 0)
    	return NULL;

    if (((info.st_mode & S_IFMT) != S_IFREG) || (info.st_size < sizeof(*fh))) {
	close(fd);
	return NULL;
    }

    if (map_fd(fd, 0, (vm_offset_t *)&fh, TRUE, (vm_size_t)info.st_size) != KERN_SUCCESS) {
	close(fd);
	return NULL;
    }

#ifdef __BIG_ENDIAN__
    if (fh->magic == FAT_MAGIC) {
#endif __BIG_ENDIAN__
#ifdef __LITTLE_ENDIAN__
    if (fh->magic == NXSwapLong(FAT_MAGIC)) {
#endif __LITTLE_ENDIAN__
	int i;
	struct fat_arch *fa = (struct fat_arch*)(fh + 1);
#ifdef __LITTLE_ENDIAN__
	enum NXByteOrder host_byte_sex = NXHostByteOrder();
	swap_fat_header(fh, host_byte_sex);
#endif __LITTLE_ENDIAN__
	if ((fh->nfat_arch <= 0) || (info.st_size < sizeof(*fh)+sizeof(*fa)*fh->nfat_arch)) {
		vm_deallocate(mach_task_self(), (vm_offset_t)fh, info.st_size);
		close(fd);
		return NULL;
	}
#ifdef __LITTLE_ENDIAN__
	swap_fat_arch(fa, fh->nfat_arch, host_byte_sex);
#endif __LITTLE_ENDIAN__
	for (i = 0; i < fh->nfat_arch; i++, fa++) {
		if (fa->cputype == hbi.cpu_type) {
//****		** check for best cpu_subtype here ** (fa->cpusubtype == hbi.cpu_subtype)
			break;	// for now, accept all subtypes
		}
	}
	if (i >= fh->nfat_arch) {
		vm_deallocate(mach_task_self(), (vm_offset_t)fh, info.st_size);
		close(fd);
 		return NULL;
	}
	archOffset = fa->offset;
	mh = (struct mach_header*)((char*)fh + archOffset);
    } else {
	archOffset = 0L;
    	mh = (struct mach_header*)fh;
    }
    
    if ((info.st_size < archOffset + sizeof(*mh)) ||
	(mh->magic != MH_MAGIC) || (mh->cputype != hbi.cpu_type) ||
	(info.st_size < archOffset + sizeof(*mh) + mh->sizeofcmds) ||
	!check_wellformed_header(mh, info.st_size - archOffset, NO)) { // bug#21223
	vm_deallocate(mach_task_self(), (vm_offset_t)fh, info.st_size);
	close(fd);
 	return NULL;
    }

    /*
     * Get the section data.
     */
    sect = getsectbynamefromheader(mh, segmentName, sectionName);
    if (sect == NULL || sect->size == 0 ||
	(info.st_size < archOffset + sect->offset + sect->size)) {
	vm_deallocate(mach_task_self(), (vm_offset_t)fh, info.st_size);
	close(fd);
	return NULL;
    }

    /*
     * Create the stream.
     */
    s = NXOpenMemory((char *)mh + sect->offset, sect->size,
	NX_READONLY);
    s->flags &= ~NX_USER_OWNS_BUF;

    /*
     * Through away the parts of the file not needed.  Assert that all
     * pages that the file lives on are used only by the file.
     */
    sect_page = round_page((vm_offset_t)mh + sect->offset + sect->size);
    mh_page = round_page((vm_offset_t)fh + info.st_size);
    if (mh_page - sect_page)
	vm_deallocate(mach_task_self(), sect_page, mh_page - sect_page);

    mh_page = trunc_page((vm_offset_t)fh);
    sect_page = trunc_page((vm_offset_t)mh + sect->offset);
    if (sect_page - mh_page)
	vm_deallocate(mach_task_self(), mh_page, sect_page - mh_page);

    if (close(fd) < 0) {
	NXCloseMemory(s, NX_FREEBUFFER);
	s = NULL;
    }

    return s;
}



NXStream *NXGetStreamOnSectionForBestArchitecture(
	const char *fileName,
	const char *segmentName,
	const char *sectionName)
{
    int             fd;
    struct stat     info;
    NXStream 	   *s = NULL;
    struct fat_header *fh;
    struct mach_header *mh;
    const struct section *sect;
    vm_offset_t mh_page, sect_page;
    unsigned long archOffset;
    unsigned int cnt = HOST_BASIC_INFO_COUNT;
    struct host_basic_info hbi;
    int fSwap = NO;

    if (host_info(mach_host_self(), HOST_BASIC_INFO, (host_info_t)(&hbi), &cnt) != KERN_SUCCESS)
      return NULL;

    fd = open(fileName, O_RDONLY, 0444);
    if (fd < 0 || fstat(fd, &info) < 0)
    	return NULL;

    if (((info.st_mode & S_IFMT) != S_IFREG) || (info.st_size < sizeof(*fh))) {
	close(fd);
	return NULL;
    }

    if (map_fd(fd, 0, (vm_offset_t *)&fh, TRUE, (vm_size_t)info.st_size) != KERN_SUCCESS) {
	close(fd);
	return NULL;
    }

#ifdef __BIG_ENDIAN__
    if (fh->magic == FAT_MAGIC) {
#endif __BIG_ENDIAN__
#ifdef __LITTLE_ENDIAN__
    if (fh->magic == NXSwapLong(FAT_MAGIC)) {
#endif __LITTLE_ENDIAN__
	int i;
	struct fat_arch *fa = (struct fat_arch*)(fh + 1);
#ifdef __LITTLE_ENDIAN__
	enum NXByteOrder host_byte_sex = NXHostByteOrder();
	swap_fat_header(fh, host_byte_sex);
#endif __LITTLE_ENDIAN__
	if ((fh->nfat_arch <= 0) || (info.st_size < sizeof(*fh)+sizeof(*fa)*fh->nfat_arch)) {
	    vm_deallocate(mach_task_self(), (vm_offset_t)fh, info.st_size);
	    close(fd);
	    return NULL;
	}
#ifdef __LITTLE_ENDIAN__
	swap_fat_arch(fa, fh->nfat_arch, host_byte_sex);
#endif __LITTLE_ENDIAN__
	for (i = 0; i < fh->nfat_arch; i++, fa++) {
	    if (fa->cputype == hbi.cpu_type) {
//****		** check for best cpu_subtype here ** (fa->cpusubtype == hbi.cpu_subtype)
		break;	// for now, accept all subtypes
	    }
	}
	if (i >= fh->nfat_arch) {
	    /*
	     * If do not have the correct cpu_type, just use the last type
	     * in file.
	     * NOTE: we could have a list passed in, and choose the best
	     *       based upon that list.
	     */
	    fa--;
	}
	archOffset = fa->offset;
	mh = (struct mach_header*)((char*)fh + archOffset);
    } else {
	archOffset = 0L;
    	mh = (struct mach_header*)fh;
    }
    
    if (info.st_size < archOffset + sizeof(*mh)) {
	vm_deallocate(mach_task_self(), (vm_offset_t)fh, info.st_size);
	close(fd);
 	return NULL;
    }
    
    /* 
     * Do we need to swap the header?  Header is always in byte-order of machine it
     * was compiled for.
     */
    if (mh->magic == NXSwapLong(MH_MAGIC)) {
	fSwap = YES;
#ifdef __LITTLE_ENDIAN__
	swap_mach_header(mh, NX_LittleEndian);
#else
	swap_mach_header(mh, NX_BigEndian);
#endif __LITTLE_ENDIAN__
    }

    
    if ((mh->magic != MH_MAGIC) ||
	(info.st_size < archOffset + sizeof(*mh) + mh->sizeofcmds) ||
	!check_wellformed_header(mh, info.st_size - archOffset, fSwap)) { // bug#21223
	vm_deallocate(mach_task_self(), (vm_offset_t)fh, info.st_size);
	close(fd);
 	return NULL;
    }

    /*
     * Get the section data.
     */
    sect = getsectbynamefromheaderwithswap(mh, segmentName, sectionName, fSwap);
    if (sect == NULL || sect->size == 0 ||
	(info.st_size < archOffset + sect->offset + sect->size)) {
	vm_deallocate(mach_task_self(), (vm_offset_t)fh, info.st_size);
	close(fd);
	return NULL;
    }

    /*
     * Create the stream.
     */
    s = NXOpenMemory((char *)mh + sect->offset, sect->size, NX_READONLY);
    s->flags &= ~NX_USER_OWNS_BUF;

    /*
     * Through away the parts of the file not needed.  Assert that all
     * pages that the file lives on are used only by the file.
     */
    sect_page = round_page((vm_offset_t)mh + sect->offset + sect->size);
    mh_page = round_page((vm_offset_t)fh + info.st_size);
    if (mh_page - sect_page)
	vm_deallocate(mach_task_self(), sect_page, mh_page - sect_page);

    mh_page = trunc_page((vm_offset_t)fh);
    sect_page = trunc_page((vm_offset_t)mh + sect->offset);
    if (sect_page - mh_page)
	vm_deallocate(mach_task_self(), mh_page, sect_page - mh_page);

    if (close(fd) < 0) {
	NXCloseMemory(s, NX_FREEBUFFER);
	s = NULL;
    }

    return s;
}