Esempio 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); 
}
Esempio 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;
}
Esempio 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;
}
Esempio 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;
}
Esempio n. 5
0
MODULE_SCOPE int
TclpLoadMemory(
    Tcl_Interp *interp,		/* Used for error reporting. */
    void *buffer,		/* Buffer containing the desired code
				 * (allocated with TclpLoadMemoryGetBuffer). */
    int size,			/* Allocation size of buffer. */
    int codeSize,		/* Size of code data read into buffer or -1 if
				 * an error occurred and the buffer should
				 * just be freed. */
    Tcl_LoadHandle *loadHandle, /* Filled with token for dynamically loaded
				 * file which will be passed back to
				 * (*unloadProcPtr)() to unload the file. */
    Tcl_FSUnloadFileProc **unloadProcPtr)
				/* Filled with address of Tcl_FSUnloadFileProc
				 * function which should be used for this
				 * file. */
{
    Tcl_DyldLoadHandle *dyldLoadHandle;
    NSObjectFileImage dyldObjFileImage = NULL;
    Tcl_DyldModuleHandle *modulePtr;
    NSModule module;
    const char *objFileImageErrMsg = NULL;

    /*
     * Try to create an object file image that we can load from.
     */

    if (codeSize >= 0) {
	NSObjectFileImageReturnCode err = NSObjectFileImageSuccess;
	const struct fat_header *fh = buffer;
	uint32_t ms = 0;
#ifndef __LP64__
	const struct mach_header *mh = NULL;
	#define mh_size  sizeof(struct mach_header)
	#define mh_magic MH_MAGIC
	#define arch_abi 0
#else
	const struct mach_header_64 *mh = NULL;
	#define mh_size  sizeof(struct mach_header_64)
	#define mh_magic MH_MAGIC_64
	#define arch_abi CPU_ARCH_ABI64
#endif

	if ((size_t) codeSize >= sizeof(struct fat_header)
		&& fh->magic == OSSwapHostToBigInt32(FAT_MAGIC)) {
	    uint32_t fh_nfat_arch = OSSwapBigToHostInt32(fh->nfat_arch);

	    /*
	     * Fat binary, try to find mach_header for our architecture
	     */

	    TclLoadDbgMsg("Fat binary, %d archs", fh_nfat_arch);
	    if ((size_t) codeSize >= sizeof(struct fat_header) +
		    fh_nfat_arch * sizeof(struct fat_arch)) {
		void *fatarchs = (char*)buffer + sizeof(struct fat_header);
		const NXArchInfo *arch = NXGetLocalArchInfo();
		struct fat_arch *fa;

		if (fh->magic != FAT_MAGIC) {
		    swap_fat_arch(fatarchs, fh_nfat_arch, arch->byteorder);
		}
		fa = NXFindBestFatArch(arch->cputype | arch_abi,
			arch->cpusubtype, fatarchs, fh_nfat_arch);
		if (fa) {
		    TclLoadDbgMsg("NXFindBestFatArch() successful: "
			    "local cputype %d subtype %d, "
			    "fat cputype %d subtype %d",
			    arch->cputype | arch_abi, arch->cpusubtype,
			    fa->cputype, fa->cpusubtype);
		    mh = (void*)((char*)buffer + fa->offset);
		    ms = fa->size;
		} else {
		    TclLoadDbgMsg("NXFindBestFatArch() failed");
		    err = NSObjectFileImageInappropriateFile;
		}
		if (fh->magic != FAT_MAGIC) {
		    swap_fat_arch(fatarchs, fh_nfat_arch, arch->byteorder);
		}
	    } else {
		TclLoadDbgMsg("Fat binary header failure");
		err = NSObjectFileImageInappropriateFile;
	    }
	} else {
	    /*
	     * Thin binary
	     */

	    TclLoadDbgMsg("Thin binary");
	    mh = buffer;
	    ms = codeSize;
	}
	if (ms && !(ms >= mh_size && mh->magic == mh_magic &&
		 mh->filetype == MH_BUNDLE)) {
	    TclLoadDbgMsg("Inappropriate file: magic %x filetype %d",
		    mh->magic, mh->filetype);
	    err = NSObjectFileImageInappropriateFile;
	}
	if (err == NSObjectFileImageSuccess) {
	    err = NSCreateObjectFileImageFromMemory(buffer, codeSize,
		    &dyldObjFileImage);
	    if (err == NSObjectFileImageSuccess) {
		TclLoadDbgMsg("NSCreateObjectFileImageFromMemory() "
			"successful");
	    } else {
		objFileImageErrMsg = DyldOFIErrorMsg(err);
		TclLoadDbgMsg("NSCreateObjectFileImageFromMemory() failed: %s",
			objFileImageErrMsg);
	    }
	} else {
	    objFileImageErrMsg = DyldOFIErrorMsg(err);
	}
    }

    /*
     * If it went wrong (or we were asked to just deallocate), get rid of the
     * memory block and create an error message.
     */

    if (dyldObjFileImage == NULL) {
	vm_deallocate(mach_task_self(), (vm_address_t) buffer, size);
	if (objFileImageErrMsg != NULL) {
	    Tcl_AppendResult(interp, "NSCreateObjectFileImageFromMemory() "
		    "error: ", objFileImageErrMsg, NULL);
	}
	return TCL_ERROR;
    }

    /*
     * Extract the module we want from the image of the object file.
     */

    module = NSLinkModule(dyldObjFileImage, "[Memory Based Bundle]",
	    NSLINKMODULE_OPTION_BINDNOW | NSLINKMODULE_OPTION_RETURN_ON_ERROR);
    NSDestroyObjectFileImage(dyldObjFileImage);
    if (module) {
	TclLoadDbgMsg("NSLinkModule() successful");
    } else {
	NSLinkEditErrors editError;
	int errorNumber;
	const char *errorName, *errMsg;

	NSLinkEditError(&editError, &errorNumber, &errorName, &errMsg);
	TclLoadDbgMsg("NSLinkModule() failed: %s", errMsg);
	Tcl_AppendResult(interp, errMsg, NULL);
	return TCL_ERROR;
    }

    /*
     * Stash the module reference within the load handle we create and return.
     */

    modulePtr = (Tcl_DyldModuleHandle *) ckalloc(sizeof(Tcl_DyldModuleHandle));
    modulePtr->module = module;
    modulePtr->nextPtr = NULL;
    dyldLoadHandle = (Tcl_DyldLoadHandle *)
	    ckalloc(sizeof(Tcl_DyldLoadHandle));
#if TCL_DYLD_USE_DLFCN
    dyldLoadHandle->dlHandle = NULL;
#endif
    dyldLoadHandle->dyldLibHeader = NULL;
    dyldLoadHandle->modulePtr = modulePtr;
    *loadHandle = (Tcl_LoadHandle) dyldLoadHandle;
    *unloadProcPtr = &TclpUnloadFile;
    return TCL_OK;
}
Esempio n. 6
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;
}