From patchwork Fri Jun 7 09:05:32 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?q?Alex_Benn=C3=A9e?= X-Patchwork-Id: 166122 Delivered-To: patch@linaro.org Received: by 2002:a92:9e1a:0:0:0:0:0 with SMTP id q26csp441728ili; Fri, 7 Jun 2019 03:15:49 -0700 (PDT) X-Google-Smtp-Source: APXvYqxeIQ4zcspewjOnPihctQuN2wQqGaFmsGdGue6kM3C4wDJHCbEGWAwfn7dM0r984vPIp5BD X-Received: by 2002:ac8:3811:: with SMTP id q17mr17089853qtb.315.1559902549117; Fri, 07 Jun 2019 03:15:49 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1559902549; cv=none; d=google.com; s=arc-20160816; b=SmPrZGzVG3mveHifTJUdqFIzL4ArU1Qpzg7MG6jO1v+E0l7nAHUpYxqKvtru3Tncqq wEZrNdvcNDilQRCyVhOThcWKHn/ljprg7R9/uyHyLce3zIO4TDTKsKS4A5Ethc2Zm2wx 0JeCN4+4nOhDF/ARKGkosXarfb3Xowduigw8F0Cm1FolABIlHmLY3C4miaceSFTSqsIs BedEI/Wr2Gl1nW+JUuOJI7BoqJg6BjN+uDfoaAtXhnwFRF/UwMLt24G3QB6QQH+7q0nl OtW/m8Brf9a/TEMM01YKJGLyab8fOs3E+6tsOEU6VkSFSAMuls6Eg9IPGmCIDNerAjOR MJ1g== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=sender:errors-to:cc:list-subscribe:list-help:list-post:list-archive :list-unsubscribe:list-id:precedence:subject :content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:to:from:dkim-signature; bh=c76UPtcUyW2+y+2t3rM60+D/f7quHWsTGj5ldY4x42E=; b=hZcbUB+B8HGvx74O7wTdOoUmPc0k0G8Kb1h7dTwn0Klxfz0KsqW3FRUqwzEVWyBU38 ZrrnumAExbLQUmkAZV6vwlVGff/zf838SuVge5Pg1t9SfoCwnmWkxIRX2PGXeXFMshle 4B+nviOSU4QFwU9GMOaVes5gPPY3/m9fXb002BGWyMv8vMfuqklelkAUM1CEzBK31E2H KUGTQwFo2Vcq9XJNmeNJ/T0T3Z/IthwHNfWrz/f8SYpPgNM3h5nrEZBUVXO1huR8O5nD c60xh3PCO+5oCsSRZV6kToQ1hE5kxDQGbuJ+ejjVcIc/Xkpp7JDAEFvsCCwmCIB2OMIE epJA== ARC-Authentication-Results: i=1; mx.google.com; dkim=fail header.i=@linaro.org header.s=google header.b=b8u1zWcE; spf=pass (google.com: domain of qemu-devel-bounces+patch=linaro.org@nongnu.org designates 209.51.188.47 as permitted sender) smtp.mailfrom="qemu-devel-bounces+patch=linaro.org@nongnu.org"; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=linaro.org Return-Path: Received: from lists.gnu.org (lists.gnu.org. [209.51.188.47]) by mx.google.com with ESMTPS id n25si840588qkg.264.2019.06.07.03.15.49 for (version=TLS1_2 cipher=ECDHE-RSA-CHACHA20-POLY1305 bits=256/256); Fri, 07 Jun 2019 03:15:49 -0700 (PDT) Received-SPF: pass (google.com: domain of qemu-devel-bounces+patch=linaro.org@nongnu.org designates 209.51.188.47 as permitted sender) client-ip=209.51.188.47; Authentication-Results: mx.google.com; dkim=fail header.i=@linaro.org header.s=google header.b=b8u1zWcE; spf=pass (google.com: domain of qemu-devel-bounces+patch=linaro.org@nongnu.org designates 209.51.188.47 as permitted sender) smtp.mailfrom="qemu-devel-bounces+patch=linaro.org@nongnu.org"; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=linaro.org Received: from localhost ([::1]:47930 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.86_2) (envelope-from ) id 1hZBuW-0004TZ-Na for patch@linaro.org; Fri, 07 Jun 2019 06:15:48 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:44992) by lists.gnu.org with esmtp (Exim 4.86_2) (envelope-from ) id 1hZB50-00088b-LP for qemu-devel@nongnu.org; Fri, 07 Jun 2019 05:22:36 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1hZB4z-0005qW-1k for qemu-devel@nongnu.org; Fri, 07 Jun 2019 05:22:34 -0400 Received: from mail-wm1-x343.google.com ([2a00:1450:4864:20::343]:50305) by eggs.gnu.org with esmtps (TLS1.0:RSA_AES_128_CBC_SHA1:16) (Exim 4.71) (envelope-from ) id 1hZB4y-0005of-QU for qemu-devel@nongnu.org; Fri, 07 Jun 2019 05:22:32 -0400 Received: by mail-wm1-x343.google.com with SMTP id c66so1283121wmf.0 for ; Fri, 07 Jun 2019 02:22:32 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=c76UPtcUyW2+y+2t3rM60+D/f7quHWsTGj5ldY4x42E=; b=b8u1zWcEiK+85KmLg3wHJQct7+7iQkVgwXQYu6+2iwEVJuNIm5aoW9HyMoYMQO1LQE Vy/k1NnQPzj5OoxYAKTL+dFA+lU6CpLqpJ28PIXBKM+zaJteHosQuFGk/pvGLqrjqYAS RLWfkmBfdC7g41j7Ddne28SZ4JCy1jOvtTFnq+gOrU/eHYUuwHBdfukYlpHOIONS7HYQ 061gQkxH1bh7WXRq8j+NpqqaIFDeiEa6/iCP6FgLgRMMdGYUrSp/b0PESSMwsAvGi4lj 0H1vbUUbd/lVWvwkh2B9PVnrKD6nGAh7xxCaS1P6RLPrtp+WfjJTOkEqh6agAk7jc5et lYAw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=c76UPtcUyW2+y+2t3rM60+D/f7quHWsTGj5ldY4x42E=; b=TP2P+/irmnM9FFU2xkerX5jPy0oqMm0gnI9f4DrHjo9wVwyV5kxiFl9Gozo4ufsjQN zRZj8GJBLPCP1m/1WLU7G2sua8M5/aU3xYFxBO1q/1xv3VoF5yhatcOM7H11faDRMt0A D69u0e70uKDh2ClDJ2K9RYma1TOgRQRmhBKaxoH2+eLBWbQuD6TCqOrWM7BxYEui5DFx MoleSLWIqgdMXpagQEl3RGzC/OA89A4k9LLgEWKcxrRum862/zVCVTsV72PDPQZaB28G /w/JT3eaHTLXT/N947ciETENmHxg981acR8wxemgC6I8eNc1KM5milLDcBdiWoinUstR kyog== X-Gm-Message-State: APjAAAW2cxkhgPrZ8pK74jEDrMZKLXRftFpyo8qskjCd844HmB41fN7N u1KOSdzgds20JFrUjEaQDWsmXQ== X-Received: by 2002:a1c:238e:: with SMTP id j136mr2722100wmj.4.1559899351642; Fri, 07 Jun 2019 02:22:31 -0700 (PDT) Received: from zen.linaroharston ([81.128.185.34]) by smtp.gmail.com with ESMTPSA id c16sm1465080wrr.53.2019.06.07.02.22.27 (version=TLS1_3 cipher=AEAD-AES256-GCM-SHA384 bits=256/256); Fri, 07 Jun 2019 02:22:30 -0700 (PDT) Received: from zen.linaroharston. (localhost [127.0.0.1]) by zen.linaroharston (Postfix) with ESMTP id A741D1FFB8; Fri, 7 Jun 2019 10:05:54 +0100 (BST) From: =?utf-8?q?Alex_Benn=C3=A9e?= To: peter.maydell@linaro.org Date: Fri, 7 Jun 2019 10:05:32 +0100 Message-Id: <20190607090552.12434-34-alex.bennee@linaro.org> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20190607090552.12434-1-alex.bennee@linaro.org> References: <20190607090552.12434-1-alex.bennee@linaro.org> MIME-Version: 1.0 X-detected-operating-system: by eggs.gnu.org: Genre and OS details not recognized. X-Received-From: 2a00:1450:4864:20::343 Subject: [Qemu-devel] [PULL 33/52] gdbstub: Add infrastructure to parse cmd packets X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: =?utf-8?q?Philippe_Mathieu-Daud=C3=A9?= , =?utf-8?q?Alex_Benn=C3=A9e?= , qemu-devel@nongnu.org, Jon Doron Errors-To: qemu-devel-bounces+patch=linaro.org@nongnu.org Sender: "Qemu-devel" From: Jon Doron Signed-off-by: Jon Doron Reviewed-by: Alex Bennée Message-Id: <20190529064148.19856-2-arilou@gmail.com> Signed-off-by: Alex Bennée -- 2.20.1 diff --git a/gdbstub.c b/gdbstub.c index 462f89edfe..09fe5a4b99 100644 --- a/gdbstub.c +++ b/gdbstub.c @@ -1268,6 +1268,201 @@ out: return res; } +typedef union GdbCmdVariant { + const char *data; + uint8_t opcode; + unsigned long val_ul; + unsigned long long val_ull; + struct { + GDBThreadIdKind kind; + uint32_t pid; + uint32_t tid; + } thread_id; +} GdbCmdVariant; + +static const char *cmd_next_param(const char *param, const char delimiter) +{ + static const char all_delimiters[] = ",;:="; + char curr_delimiters[2] = {0}; + const char *delimiters; + + if (delimiter == '?') { + delimiters = all_delimiters; + } else if (delimiter == '0') { + return strchr(param, '\0'); + } else if (delimiter == '.' && *param) { + return param + 1; + } else { + curr_delimiters[0] = delimiter; + delimiters = curr_delimiters; + } + + param += strcspn(param, delimiters); + if (*param) { + param++; + } + return param; +} + +static int cmd_parse_params(const char *data, const char *schema, + GdbCmdVariant *params, int *num_params) +{ + int curr_param; + const char *curr_schema, *curr_data; + + *num_params = 0; + + if (!schema) { + return 0; + } + + curr_schema = schema; + curr_param = 0; + curr_data = data; + while (curr_schema[0] && curr_schema[1] && *curr_data) { + switch (curr_schema[0]) { + case 'l': + if (qemu_strtoul(curr_data, &curr_data, 16, + ¶ms[curr_param].val_ul)) { + return -EINVAL; + } + curr_param++; + curr_data = cmd_next_param(curr_data, curr_schema[1]); + break; + case 'L': + if (qemu_strtou64(curr_data, &curr_data, 16, + (uint64_t *)¶ms[curr_param].val_ull)) { + return -EINVAL; + } + curr_param++; + curr_data = cmd_next_param(curr_data, curr_schema[1]); + break; + case 's': + params[curr_param].data = curr_data; + curr_param++; + curr_data = cmd_next_param(curr_data, curr_schema[1]); + break; + case 'o': + params[curr_param].opcode = *(uint8_t *)curr_data; + curr_param++; + curr_data = cmd_next_param(curr_data, curr_schema[1]); + break; + case 't': + params[curr_param].thread_id.kind = + read_thread_id(curr_data, &curr_data, + ¶ms[curr_param].thread_id.pid, + ¶ms[curr_param].thread_id.tid); + curr_param++; + curr_data = cmd_next_param(curr_data, curr_schema[1]); + break; + case '?': + curr_data = cmd_next_param(curr_data, curr_schema[1]); + break; + default: + return -EINVAL; + } + curr_schema += 2; + } + + *num_params = curr_param; + return 0; +} + +typedef struct GdbCmdContext { + GDBState *s; + GdbCmdVariant *params; + int num_params; + uint8_t mem_buf[MAX_PACKET_LENGTH]; + char str_buf[MAX_PACKET_LENGTH + 1]; +} GdbCmdContext; + +typedef void (*GdbCmdHandler)(GdbCmdContext *gdb_ctx, void *user_ctx); + +/* + * cmd_startswith -> cmd is compared using startswith + * + * + * schema definitions: + * Each schema parameter entry consists of 2 chars, + * the first char represents the parameter type handling + * the second char represents the delimiter for the next parameter + * + * Currently supported schema types: + * 'l' -> unsigned long (stored in .val_ul) + * 'L' -> unsigned long long (stored in .val_ull) + * 's' -> string (stored in .data) + * 'o' -> single char (stored in .opcode) + * 't' -> thread id (stored in .thread_id) + * '?' -> skip according to delimiter + * + * Currently supported delimiters: + * '?' -> Stop at any delimiter (",;:=\0") + * '0' -> Stop at "\0" + * '.' -> Skip 1 char unless reached "\0" + * Any other value is treated as the delimiter value itself + */ +typedef struct GdbCmdParseEntry { + GdbCmdHandler handler; + const char *cmd; + bool cmd_startswith; + const char *schema; +} GdbCmdParseEntry; + +static inline int startswith(const char *string, const char *pattern) +{ + return !strncmp(string, pattern, strlen(pattern)); +} + +static int process_string_cmd( + GDBState *s, void *user_ctx, const char *data, + const GdbCmdParseEntry *cmds, int num_cmds) + __attribute__((unused)); + +static int process_string_cmd(GDBState *s, void *user_ctx, const char *data, + const GdbCmdParseEntry *cmds, int num_cmds) +{ + int i, schema_len, max_num_params = 0; + GdbCmdContext gdb_ctx; + + if (!cmds) { + return -1; + } + + for (i = 0; i < num_cmds; i++) { + const GdbCmdParseEntry *cmd = &cmds[i]; + g_assert(cmd->handler && cmd->cmd); + + if ((cmd->cmd_startswith && !startswith(data, cmd->cmd)) || + (!cmd->cmd_startswith && strcmp(cmd->cmd, data))) { + continue; + } + + if (cmd->schema) { + schema_len = strlen(cmd->schema); + if (schema_len % 2) { + return -2; + } + + max_num_params = schema_len / 2; + } + + gdb_ctx.params = + (GdbCmdVariant *)alloca(sizeof(*gdb_ctx.params) * max_num_params); + memset(gdb_ctx.params, 0, sizeof(*gdb_ctx.params) * max_num_params); + + if (cmd_parse_params(&data[strlen(cmd->cmd)], cmd->schema, + gdb_ctx.params, &gdb_ctx.num_params)) { + return -1; + } + + gdb_ctx.s = s; + cmd->handler(&gdb_ctx, user_ctx); + return 0; + } + + return -1; +} + static int gdb_handle_packet(GDBState *s, const char *line_buf) { CPUState *cpu;