예제 #1
0
debugserver_error_t debugserver_client_set_environment_hex_encoded(debugserver_client_t client, const char* env, char** response)
{
	if (!client || !env)
		return DEBUGSERVER_E_INVALID_ARG;

	debugserver_error_t result = DEBUGSERVER_E_UNKNOWN_ERROR;
	const char* env_arg[] = { env, NULL };

	debugserver_command_t command = NULL;
	debugserver_command_new("QEnvironmentHexEncoded:", 1, env_arg, &command);
	result = debugserver_client_send_command(client, command, response);
	debugserver_command_free(command);

	return result;
}
예제 #2
0
debugserver_error_t debugserver_client_set_argv(debugserver_client_t client, int argc, char* argv[], char** response)
{
	if (!client || !argc)
		return DEBUGSERVER_E_INVALID_ARG;

	debugserver_error_t result = DEBUGSERVER_E_UNKNOWN_ERROR;
	char *pkt = NULL;
	int pkt_len = 0;
	int i = 0;

	/* calculate total length */
	while (i < argc && argv && argv[i]) {
		char *prefix = NULL;
		asprintf(&prefix, ",%d,%d,", (int)strlen(argv[i]) * 2, i);
		pkt_len += (int)strlen(prefix) + (int)strlen(argv[i]) * 2;
		free(prefix);
		i++;
	}

	/* allocate packet and initialize it */
	pkt = (char *) malloc(pkt_len + 1);
	memset(pkt, 0, pkt_len + 1);

	char *pktp = pkt;

	i = 0;
	while (i < argc && argv && argv[i]) {
		debug_info("argv[%d] = \"%s\"", i, argv[i]);

		char *prefix = NULL;
		char *m = NULL;
		int arg_len = strlen(argv[i]);
		int arg_hexlen = arg_len * 2;

		asprintf(&prefix, ",%d,%d,", arg_hexlen, i);

		m = (char *) malloc(arg_hexlen);
		char *p = m;
		char *q = (char*)argv[i];
		while (*q) {
			*p++ = debugserver_int2hex(*q >> 4);
			*p++ = debugserver_int2hex(*q & 0xf);
			q++;
		}

		memcpy(pktp, prefix, strlen(prefix));
		pktp += strlen(prefix);

		memcpy(pktp, m, arg_hexlen);
		pktp += arg_hexlen;

		free(prefix);
		free(m);

		i++;
	}

	pkt[0] = 'A';

	debugserver_command_t command = NULL;
	debugserver_command_new(pkt, 0, NULL, &command);
	result = debugserver_client_send_command(client, command, response);
	debugserver_command_free(command);

	if (pkt)
		free(pkt);

	return result;
}
예제 #3
0
int main(int argc, char *argv[])
{
    int res = -1;
    idevice_t device = NULL;
    idevice_error_t ret = IDEVICE_E_UNKNOWN_ERROR;
    instproxy_client_t instproxy_client = NULL;
    debugserver_client_t debugserver_client = NULL;
    int i;
    int debug_level = 0;
    int cmd = CMD_NONE;
    const char* udid = NULL;
    const char* bundle_identifier = NULL;
    char* path = NULL;
    char* working_directory = NULL;
    char **newlist = NULL;
    char** environment = NULL;
    int environment_index = 0;
    int environment_count = 0;
    char* response = NULL;
    debugserver_command_t command = NULL;
    debugserver_error_t dres = DEBUGSERVER_E_UNKNOWN_ERROR;

    /* map signals */
    signal(SIGINT, on_signal);
    signal(SIGTERM, on_signal);
#ifndef WIN32
    signal(SIGQUIT, on_signal);
    signal(SIGPIPE, SIG_IGN);
#endif

    /* parse command line arguments */
    for (i = 1; i < argc; i++) {
        if (!strcmp(argv[i], "-d") || !strcmp(argv[i], "--debug")) {
            debug_level++;
            idevice_set_debug_level(debug_level);
            continue;
        } else if (!strcmp(argv[i], "-u") || !strcmp(argv[i], "--udid")) {
            i++;
            if (!argv[i] || (strlen(argv[i]) != 40)) {
                print_usage(argc, argv);
                res = 0;
                goto cleanup;
            }
            udid = argv[i];
            continue;
        } else if (!strcmp(argv[i], "-e") || !strcmp(argv[i], "--env")) {
            i++;
            if (!argv[i] || (strlen(argv[i]) <= 1) || strchr(argv[i], '=') == NULL) {
                print_usage(argc, argv);
                res = 0;
                goto cleanup;
            }
            /* add environment variable */
            if (!newlist)
                newlist = malloc((environment_count + 1) * sizeof(char*));
            else
                newlist = realloc(environment, (environment_count + 1) * sizeof(char*));
            newlist[environment_count++] = strdup(argv[i]);
            environment = newlist;
            continue;
        } else if (!strcmp(argv[i], "-h") || !strcmp(argv[i], "--help")) {
            print_usage(argc, argv);
            res = 0;
            goto cleanup;
        } else if (!strcmp(argv[i], "run")) {
            cmd = CMD_RUN;

            i++;
            if (!argv[i]) {
                /* make sure at least the bundle identifier was provided */
                printf("Please supply the bundle identifier of the app to run.\n");
                print_usage(argc, argv);
                res = 0;
                goto cleanup;
            }
            /*  read bundle identifier */
            bundle_identifier = argv[i];
            break;
        } else {
            print_usage(argc, argv);
            res = 0;
            goto cleanup;
        }
    }

    if (environment) {
        newlist = realloc(environment, (environment_count + 1) * sizeof(char*));
        newlist[environment_count] = NULL;
        environment = newlist;
    }

    /* verify options */
    if (cmd == CMD_NONE) {
        print_usage(argc, argv);
        goto cleanup;
    }

    /* connect to the device */
    ret = idevice_new(&device, udid);
    if (ret != IDEVICE_E_SUCCESS) {
        if (udid) {
            printf("No device found with udid %s, is it plugged in?\n", udid);
        } else {
            printf("No device found, is it plugged in?\n");
        }
        goto cleanup;
    }

    switch (cmd) {
    case CMD_RUN:
    default:
        /* get the path to the app and it's working directory */
        if (instproxy_client_start_service(device, &instproxy_client, "idevicerun") != INSTPROXY_E_SUCCESS) {
            fprintf(stderr, "Could not start installation proxy service.\n");
            goto cleanup;
        }
        plist_t container = NULL;
        instproxy_client_get_object_by_key_from_info_directionary_for_bundle_identifier(instproxy_client, bundle_identifier, "Container", &container);
        instproxy_client_get_path_for_bundle_identifier(instproxy_client, bundle_identifier, &path);
        instproxy_client_free(instproxy_client);
        instproxy_client = NULL;

        if (container && (plist_get_node_type(container) == PLIST_STRING)) {
            plist_get_string_val(container, &working_directory);
            debug_info("working_directory: %s\n", working_directory);
            plist_free(container);
        } else {
            plist_free(container);
            fprintf(stderr, "Could not determine container path for bundle identifier %s.\n", bundle_identifier);
            goto cleanup;
        }

        /* start and connect to debugserver */
        if (debugserver_client_start_service(device, &debugserver_client, "idevicerun") != DEBUGSERVER_E_SUCCESS) {
            fprintf(stderr,
                    "Could not start com.apple.debugserver!\n"
                    "Please make sure to mount the developer disk image first:\n"
                    "  1) Get the iOS version from `ideviceinfo -k ProductVersion`.\n"
                    "  2) Find the matching iPhoneOS DeveloperDiskImage.dmg files.\n"
                    "  3) Run `ideviceimagemounter` with the above path.\n");
            goto cleanup;
        }

        /* enable logging for the session in debug mode */
        if (debug_level) {
            debug_info("Setting logging bitmask...");
            debugserver_command_new("QSetLogging:bitmask=LOG_ALL|LOG_RNB_REMOTE|LOG_RNB_PACKETS", 0, NULL, &command);
            dres = debugserver_client_send_command(debugserver_client, command, &response);
            debugserver_command_free(command);
            command = NULL;
            if (response) {
                if (strncmp(response, "OK", 2)) {
                    debugserver_client_handle_response(debugserver_client, &response, 0);
                    goto cleanup;
                }
                free(response);
                response = NULL;
            }
        }

        /* set maximum packet size */
        debug_info("Setting maximum packet size...");
        char* packet_size[2] = {strdup("1024"), NULL};
        debugserver_command_new("QSetMaxPacketSize:", 1, packet_size, &command);
        free(packet_size[0]);
        dres = debugserver_client_send_command(debugserver_client, command, &response);
        debugserver_command_free(command);
        command = NULL;
        if (response) {
            if (strncmp(response, "OK", 2)) {
                debugserver_client_handle_response(debugserver_client, &response, 0);
                goto cleanup;
            }
            free(response);
            response = NULL;
        }

        /* set working directory */
        debug_info("Setting working directory...");
        char* working_dir[2] = {working_directory, NULL};
        debugserver_command_new("QSetWorkingDir:", 1, working_dir, &command);
        dres = debugserver_client_send_command(debugserver_client, command, &response);
        debugserver_command_free(command);
        command = NULL;
        if (response) {
            if (strncmp(response, "OK", 2)) {
                debugserver_client_handle_response(debugserver_client, &response, 0);
                goto cleanup;
            }
            free(response);
            response = NULL;
        }

        /* set environment */
        if (environment) {
            debug_info("Setting environment...");
            for (environment_index = 0; environment_index < environment_count; environment_index++) {
                debug_info("setting environment variable: %s", environment[environment_index]);
                debugserver_client_set_environment_hex_encoded(debugserver_client, environment[environment_index], NULL);
            }
        }

        /* set arguments and run app */
        debug_info("Setting argv...");
        i++; /* i is the offset of the bundle identifier, thus skip it */
        int app_argc = (argc - i + 2);
        char **app_argv = (char**)malloc(sizeof(char*) * app_argc);
        app_argv[0] = path;
        debug_info("app_argv[%d] = %s", 0, app_argv[0]);
        app_argc = 1;
        while (i < argc && argv && argv[i]) {
            debug_info("app_argv[%d] = %s", app_argc, argv[i]);
            app_argv[app_argc++] = argv[i];
            i++;
        }
        app_argv[app_argc] = NULL;
        debugserver_client_set_argv(debugserver_client, app_argc, app_argv, NULL);
        free(app_argv);

        /* check if launch succeeded */
        debug_info("Checking if launch succeeded...");
        debugserver_command_new("qLaunchSuccess", 0, NULL, &command);
        dres = debugserver_client_send_command(debugserver_client, command, &response);
        debugserver_command_free(command);
        command = NULL;
        if (response) {
            if (strncmp(response, "OK", 2)) {
                debugserver_client_handle_response(debugserver_client, &response, 0);
                goto cleanup;
            }
            free(response);
            response = NULL;
        }

        /* set thread */
        debug_info("Setting thread...");
        debugserver_command_new("Hc0", 0, NULL, &command);
        dres = debugserver_client_send_command(debugserver_client, command, &response);
        debugserver_command_free(command);
        command = NULL;
        if (response) {
            if (strncmp(response, "OK", 2)) {
                debugserver_client_handle_response(debugserver_client, &response, 0);
                goto cleanup;
            }
            free(response);
            response = NULL;
        }

        /* continue running process */
        debug_info("Continue running process...");
        debugserver_command_new("c", 0, NULL, &command);
        dres = debugserver_client_send_command(debugserver_client, command, &response);
        debugserver_command_free(command);
        command = NULL;

        /* main loop which is parsing/handling packets during the run */
        debug_info("Entering run loop...");
        while (!quit_flag) {
            if (dres != DEBUGSERVER_E_SUCCESS) {
                debug_info("failed to receive response");
                break;
            }

            if (response) {
                debug_info("response: %s", response);
                dres = debugserver_client_handle_response(debugserver_client, &response, 1);
            }

            sleep(1);
        }

        /* kill process after we finished */
        debug_info("Killing process...");
        debugserver_command_new("k", 0, NULL, &command);
        dres = debugserver_client_send_command(debugserver_client, command, &response);
        debugserver_command_free(command);
        command = NULL;
        if (response) {
            if (strncmp(response, "OK", 2)) {
                debugserver_client_handle_response(debugserver_client, &response, 0);
                goto cleanup;
            }
            free(response);
            response = NULL;
        }

        res = (dres == DEBUGSERVER_E_SUCCESS) ? 0: -1;
        break;
    }

cleanup:
    /* cleanup the house */
    if (environment) {
        for (environment_index = 0; environment_index < environment_count; environment_index++) {
            free(environment[environment_index]);
        }
        free(environment);
    }

    if (working_directory)
        free(working_directory);

    if (path)
        free(path);

    if (response)
        free(response);

    if (debugserver_client)
        debugserver_client_free(debugserver_client);

    if (device)
        idevice_free(device);

    return res;
}
예제 #4
0
static debugserver_error_t debugserver_client_handle_response(debugserver_client_t client, char** response, int send_reply)
{
    debugserver_error_t dres = DEBUGSERVER_E_SUCCESS;
    debugserver_command_t command = NULL;
    char* o = NULL;
    char* r = *response;

    if (r[0] == 'O') {
        /* stdout/stderr */
        debugserver_decode_string(r + 1, strlen(r) - 1, &o);
        printf("%s", o);
        fflush(stdout);
        if (o != NULL) {
            free(o);
            o = NULL;
        }

        free(*response);
        *response = NULL;

        if (!send_reply)
            return dres;

        /* send reply */
        debugserver_command_new("OK", 0, NULL, &command);
        dres = debugserver_client_send_command(client, command, response);
        debug_info("result: %d", dres);
        debugserver_command_free(command);
        command = NULL;
    } else if (r[0] == 'T') {
        /* thread stopped information */
        debug_info("Thread stopped. Details:\n%s", r + 1);

        free(*response);
        *response = NULL;

        if (!send_reply)
            return dres;

        dres = DEBUGSERVER_E_UNKNOWN_ERROR;
    } else if (r[0] == 'E' || r[0] == 'W') {
        printf("%s: %s\n", (r[0] == 'E' ? "ERROR": "WARNING") , r + 1);

        free(*response);
        *response = NULL;

        if (!send_reply)
            return dres;

        /* send reply */
        debugserver_command_new("OK", 0, NULL, &command);
        dres = debugserver_client_send_command(client, command, response);
        debug_info("result: %d", dres);
        debugserver_command_free(command);
        command = NULL;
    } else if (r && strlen(r) == 0) {
        if (!send_reply)
            return dres;

        free(*response);
        *response = NULL;

        /* no command */
        debugserver_command_new("OK", 0, NULL, &command);
        dres = debugserver_client_send_command(client, command, response);
        debug_info("result: %d", dres);
        debugserver_command_free(command);
        command = NULL;
    } else {
        debug_info("ERROR: unhandled response", r);
    }

    return dres;
}