Exemple #1
0
DylibSearch::DylibSearch()
	: m_reFrameworkPath("/System/Library/Frameworks/([a-zA-Z0-9\\.]+)/Versions/([a-zA-Z0-9\\.]+)/.*"),
	m_reDefaultFrameworkPath("/System/Library/Frameworks/([a-zA-Z0-9\\.]+)/([a-zA-Z0-9\\.]+)")
{
	try
	{
		if (__prefix_get() != nullptr)
			m_config = new IniConfig(__prefix_translate_path(ETC_DARLING_PATH "/dylib.conf"));
		else
			m_config = new IniConfig(LIBEXEC_PATH ETC_DARLING_PATH "/dylib.conf");
	}
	catch (const std::exception& e)
	{
		std::cerr << e.what() << std::endl;
	}
}
Exemple #2
0
std::string DylibSearch::resolveInPathList(std::string name, const std::vector<std::string>& paths)
{
	const char* prefix = __prefix_get();
	for (const std::string& e : paths)
	{
		std::string path;
		
		if (prefix)
			path = prefix;
		
		path += e + "/" + name;

		if (::access(path.c_str(), F_OK) == 0)
			return path;
	}

	return std::string();
}
Exemple #3
0
std::string DylibSearch::resolve(std::string dylib, MachOObject* requester)
{
	if (dylib.empty())
		return std::string();

	// expand @rpath, @executable_path and @loader_path
	if (requester != nullptr && dylib[0] == '@')
	{
		if (dylib.compare(0, 16, "@executable_path") == 0)
		{
			MachOObject* mainModule = MachOMgr::instance()->mainModule();
			
			if (!mainModule)
				throw std::runtime_error("Cannot resolve @executable_path without a main module");
			
			dylib.replace(0, 16, mainModule->directory());
		}
		else if (dylib.compare(0, 12, "@loader_path") == 0)
		{
			dylib.replace(0, 12, requester->directory());
		}
		else if (dylib.compare(0, 6, "@rpath") == 0)
		{
			return resolveViaRpath(dylib, requester);
		}
	}
	
	// Search in configuration
	if (const char* aliasTarget = resolveAlias(dylib))
	{
		std::string p;
		
		if (!strchr(aliasTarget, '/'))
		{
			p = LIB_PATH;
			p += '/';
			p += aliasTarget;
			// std::cout << p << std::endl;
		}
		
		return p;
	}
	
	// Search in extra paths
	std::string epath;
	epath = resolveInPathList(dylib, m_extraPaths);
	if (!epath.empty())
		return epath;
	
	// Search in DYLD_LIBRARY_PATH
	epath = resolveInLdPath(dylib);
	if (!epath.empty())
		return epath;
	
	// Try the path as is
	epath = checkPresence(dylib);
	if (!epath.empty())
		return epath;

	// If absolute, search in sysroot
	if (dylib[0] == '/')
	{
		const char* prefix = __prefix_get();
		
		if (!MachOMgr::instance()->sysRoot().empty())
		{
			std::vector<std::string> roots = string_explode(MachOMgr::instance()->sysRoot(), ':');

			for (const std::string& in_path : roots)
			{
				std::string path;
				
				if (prefix != nullptr)
					path = prefix;
				
				path += in_path;
				path += '/';
				path += dylib;

				epath = checkPresence(path);
				if (!epath.empty())
					return epath;
			}
		}
		if (prefix != nullptr)
		{
			std::string path = prefix;
			path += dylib;
			
			epath = checkPresence(path);
			if (!epath.empty())
				return epath;
		}
	}
	
	/*if (MachOMgr::instance()->ignoreMissingDependencies())
	{
		
	}*/

	return std::string();
}
Exemple #4
0
long sys_execve(char* fname, char** argvp, char** envp)
{
	int ret, fd;
	char dyld_path[256];
	union
	{
		uint32_t magic;
		char magic_array[256];
	} m;

	// Ideally, if everybody used binfmt_misc to allow direct
	// execution of Mach-O binaries under Darling, this wouldn't
	// be necessary. But we cannot rely on that.
	
	fd = sys_open(fname, BSD_O_RDONLY, 0);
	if (fd < 0)
		return fd;

	ret = sys_read(fd, m.magic_array, sizeof(m.magic_array));
	if (ret < 4)
		goto no_macho;
	
	if (__prefix_get() != NULL)
	{
		// Inject DPREFIX if DPREFIX is missing
		int i;
		bool has_dprefix = false;
		char** new_envp;
		
		for (i = 0; envp[i] != NULL; i++)
		{
			if (strncmp(envp[i], "DPREFIX=", 8) == 0)
			{
				has_dprefix = true;
				break;
			}
		}
		
		if (!has_dprefix)
		{
			char* dprefix;
			
			new_envp = (char**) __builtin_alloca(sizeof(char*) * (i+1));
			dprefix = (char*) __builtin_alloca(strlen(__prefix_get()) + 9);
			
			for (i = 0; envp[i] != NULL; i++)
				new_envp[i] = envp[i];
			
			strcpy(dprefix, "DPREFIX=");
			strcat(dprefix, __prefix_get());
			new_envp[i++] = dprefix;
			new_envp[i] = NULL;
			
			envp = new_envp;
		}
	}

	if (m.magic == MH_MAGIC || m.magic == MH_CIGAM
			|| m.magic == MH_MAGIC_64 || m.magic == MH_CIGAM_64
			|| m.magic == FAT_MAGIC || m.magic == FAT_CIGAM)
	{
		// It is a Mach-O file
		int len, i;
		char** modargvp;
		
		len = __prefix_get_dyld_path(dyld_path, sizeof(dyld_path)-1);
		if (len < 0)
			goto no_macho;

		// Remove 64 or 32 suffix if present
		if (strcmp(&dyld_path[len - 2], "32") == 0
				|| strcmp(&dyld_path[len - 2], "64") == 0)
		{
			dyld_path[len-2] = '\0';
		}

		// Prepend dyld path
		len = 0;

		// Count arguments
		while (argvp[len++]);

		// Allocate a new argvp, execute dyld_path
		modargvp = (char**) __builtin_alloca(sizeof(void*) * (len+1));
		modargvp[0] = dyld_path;
		modargvp[1] = (char*) __prefix_translate_path_link(fname);

		for (i = 2; i < len+1; i++)
			modargvp[i] = argvp[i-1];

		argvp = modargvp;
		fname = dyld_path;
	}
	else if (__prefix_get() != NULL)
	{
		// shebang handling...
		if (m.magic_array[0] == '#' && m.magic_array[1] == '!')
		{
			char *nl, *interp, *arg;
			char** modargvp;
			int i, j, len;
			
			nl = memchr(m.magic_array, '\n', sizeof(m.magic_array));
			if (nl == NULL)
				goto no_macho;
			
			*nl = '\0';
			
			for (i = 2; isspace(m.magic_array[i]); i++);
			
			interp = &m.magic_array[i];
			
			for (i = 0; !isspace(interp[i]) && interp[i]; i++);
			
			if (interp[i] == '\0')
				arg = NULL;
			else
				arg = &interp[i];
			
			if (arg != NULL)
			{
				*arg = '\0'; // terminate interp
				while (isspace(*arg))
					arg++;
				if (*arg == '\0')
					arg = NULL; // no argument, just whitespace
			}
			
			// Count original arguments
			while (argvp[len++]);
			
			// Allocate a new argvp
			modargvp = (char**) __builtin_alloca(sizeof(void*) * (len+2));
			
			i = 0;
			modargvp[i++] = interp;
			if (arg != NULL)
				modargvp[i++] = arg;
			modargvp[i] = fname;
			
			// Append original arguments
			for (j = 1; j < len+1; j++)
				modargvp[i+j] = argvp[j];
			
			argvp = modargvp;
			fname = (char*) __prefix_translate_path(modargvp[0]);
		}
		else
		{
			fname = (char*) __prefix_translate_path_link(fname);
		}
	}

no_macho:
	sys_close(fd);

	ret = LINUX_SYSCALL(__NR_execve, fname, argvp, envp);
	if (ret < 0)
		ret = errno_linux_to_bsd(ret);

	return ret;
}