From nobody Sun Feb 8 22:07:08 2026 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Authentication-Results: mx.zohomail.com; dkim=fail; spf=pass (zoho.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=fail(p=none dis=none) header.from=gmail.com ARC-Seal: i=1; a=rsa-sha256; t=1556785112; cv=none; d=zoho.com; s=zohoarc; b=f3P39PjsPhLGdVaQllQNaDm5mLr9M9o4TCQOn6B8TymxcyqDYUY1tYkUyzpCyZ/mttDh/9HlAvzK4G781UiYzLHLmOZOIw3dl6yUnNh87SZk7qo7Gg/3RIhyZWLe9v9wgRXKgG98bBUwg1djtxG5ZBLU4rJrI67bwJzc7+OHRC4= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zoho.com; s=zohoarc; t=1556785112; h=Content-Transfer-Encoding:Cc:Date:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:To:ARC-Authentication-Results; bh=9gs1pjZcHlRiuvyF89Xf0dDUFOI/nZh6LcrIM/HDQRg=; b=SEP7zun6X5eXjzFGIKRQ9ddH6tLEU8S6lkY4tHknT3l41RIw+3rOWagZu6m3PdUzYyav0v6OMU9pmL33Iw+s48PTXpczPJQhkQh+W0gv4XeZs+qQwy2IGhy22/YxTU4l4n0a5IkZIeibJSKsd96gvVYAEzdHy8rVMlwxNtjx+ng= ARC-Authentication-Results: i=1; mx.zoho.com; dkim=fail; spf=pass (zoho.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=fail header.from= (p=none dis=none) header.from= Return-Path: Received: from lists.gnu.org (209.51.188.17 [209.51.188.17]) by mx.zohomail.com with SMTPS id 1556785112204122.74044738070847; Thu, 2 May 2019 01:18:32 -0700 (PDT) Received: from localhost ([127.0.0.1]:47188 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1hM6v9-0004EA-19 for importer@patchew.org; Thu, 02 May 2019 04:18:23 -0400 Received: from eggs.gnu.org ([209.51.188.92]:42461) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1hM6t1-000351-CM for qemu-devel@nongnu.org; Thu, 02 May 2019 04:16:12 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1hM6sz-0007Eo-Le for qemu-devel@nongnu.org; Thu, 02 May 2019 04:16:11 -0400 Received: from mail-wr1-x442.google.com ([2a00:1450:4864:20::442]:42034) by eggs.gnu.org with esmtps (TLS1.0:RSA_AES_128_CBC_SHA1:16) (Exim 4.71) (envelope-from ) id 1hM6sz-00079X-FL for qemu-devel@nongnu.org; Thu, 02 May 2019 04:16:09 -0400 Received: by mail-wr1-x442.google.com with SMTP id l2so1983812wrb.9 for ; Thu, 02 May 2019 01:16:08 -0700 (PDT) Received: from localhost.localdomain ([176.230.64.186]) by smtp.gmail.com with ESMTPSA id d16sm44698367wra.54.2019.05.02.01.16.05 (version=TLS1_2 cipher=ECDHE-RSA-CHACHA20-POLY1305 bits=256/256); Thu, 02 May 2019 01:16:06 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=9gs1pjZcHlRiuvyF89Xf0dDUFOI/nZh6LcrIM/HDQRg=; b=PS9HWP/MIAjLGJXkZy0nraGanI83qmx++phe56i5PKbGKQ/Np2Cvscj+g3cJuoRKB4 N9w4nHBoTdBKsMBnv9XmYTDlpOGSyztKcvwd0a1l4QAGVImZ2okgwNV2BgUtQ3IvEceg fiXEWUQGf1ni1vw82FXNIo/RXNfX+Y1fYpNnDanolb6xqnlHWmHqYfnrVnfXr+G1jhWv fTsGKSqUdPVvjMQHnts9z7Uguh5jYGEV9r+6tulIm+Pq26XFCeEUwJff5ShoumfSCI5f jDrgt0Kf+f+mXiANGSJOTBpxeSyXdRRg2BsfdOQiMG7OgOco43eDbUMXqkzViFwcg0rp 5Ocg== 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=9gs1pjZcHlRiuvyF89Xf0dDUFOI/nZh6LcrIM/HDQRg=; b=e70Wsg7I1/CvDnsUk0Jc2CqA+c79VsqpKVgLPzYmzeRJMgjVhUjzJYcIpZL2w6QCBs lMn66dAFZClpw1A1nroK/4bPKuk42hEneOfAEVJr8EURfa8c08vGuPfqsLgaHgAjBI8Y YGbHdpMLaGQios1bfAkru6AZZDq8wEfancS3izlccQG1bq5ouKLoNrXJq1ahLToOrsRf IaeEYj5zlmf7WdQlVLbMLP4+JrKBSpkOkVJpQqXEm8Pu0RxOPRKKncu3qzMySpNr4QSH 4gLBlu/xf9uL+mkSGNH/ZERhBflmgvV1IgS356oi+FPnfFCZnT3VGeWS56fJ78ZOsLF/ bbyA== X-Gm-Message-State: APjAAAUf03bXnmS8OnVDsLeBZdv/EVjTAQLSD9tjFoKXPoxKuhNgc7NL T1g6KTraQRqAqha/e2w9HRB8ARoG X-Google-Smtp-Source: APXvYqyMliQOexKRZ0Rcdic0GRF1LnwZl8zGkbeAaF30CrIt8BHJtFqA19XrawNPEJrTAWXptTOGfQ== X-Received: by 2002:adf:eec8:: with SMTP id a8mr1733251wrp.64.1556784967273; Thu, 02 May 2019 01:16:07 -0700 (PDT) From: Jon Doron To: qemu-devel@nongnu.org Date: Thu, 2 May 2019 11:15:28 +0300 Message-Id: <20190502081554.5521-2-arilou@gmail.com> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20190502081554.5521-1-arilou@gmail.com> References: <20190502081554.5521-1-arilou@gmail.com> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-detected-operating-system: by eggs.gnu.org: Genre and OS details not recognized. X-Received-From: 2a00:1450:4864:20::442 Subject: [Qemu-devel] [PATCH v9 01/27] gdbstub: Add infrastructure to parse cmd packets X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: alex.bennee@linaro.org, Jon Doron Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail-DKIM: fail (Header signature does not verify) Content-Type: text/plain; charset="utf-8" Signed-off-by: Jon Doron Reviewed-by: Alex Benn=C3=A9e --- gdbstub.c | 200 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 200 insertions(+) diff --git a/gdbstub.c b/gdbstub.c index d54abd17cc..d5e0f3878a 100644 --- a/gdbstub.c +++ b/gdbstub.c @@ -1268,6 +1268,206 @@ out: return res; } =20 +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[] =3D ",;:=3D"; + char curr_delimiters[2] =3D {0}; + const char *delimiters; + + if (delimiter =3D=3D '?') { + delimiters =3D all_delimiters; + } else if (delimiter =3D=3D '0') { + return strchr(param, '\0'); + } else if (delimiter =3D=3D '.' && *param) { + return param + 1; + } else { + curr_delimiters[0] =3D delimiter; + delimiters =3D curr_delimiters; + } + + param +=3D 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 =3D 0; + + if (!schema) { + return 0; + } + + curr_schema =3D schema; + curr_param =3D 0; + curr_data =3D 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 =3D 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 =3D cmd_next_param(curr_data, curr_schema[1]); + break; + case 's': + params[curr_param].data =3D curr_data; + curr_param++; + curr_data =3D cmd_next_param(curr_data, curr_schema[1]); + break; + case 'o': + params[curr_param].opcode =3D *(uint8_t *)curr_data; + curr_param++; + curr_data =3D cmd_next_param(curr_data, curr_schema[1]); + break; + case 't': + params[curr_param].thread_id.kind =3D + read_thread_id(curr_data, &curr_data, + ¶ms[curr_param].thread_id.pid, + ¶ms[curr_param].thread_id.tid); + curr_param++; + curr_data =3D cmd_next_param(curr_data, curr_schema[1]); + break; + case '?': + curr_data =3D cmd_next_param(curr_data, curr_schema[1]); + break; + default: + return -EINVAL; + } + curr_schema +=3D 2; + } + + *num_params =3D 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 (",;:=3D\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; + union { + int flags; + struct { + int cmd_startswith:1; + }; + }; + 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 *dat= a, + const GdbCmdParseEntry *cmds, int num_cmds) +{ + int i, schema_len, max_num_params =3D 0; + GdbCmdContext gdb_ctx; + + if (!cmds) { + return -1; + } + + for (i =3D 0; i < num_cmds; i++) { + const GdbCmdParseEntry *cmd =3D &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 =3D strlen(cmd->schema); + if (schema_len % 2) { + return -2; + } + + max_num_params =3D schema_len / 2; + } + + gdb_ctx.params =3D + (GdbCmdVariant *)alloca(sizeof(*gdb_ctx.params) * max_num_para= ms); + 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 =3D s; + cmd->handler(&gdb_ctx, user_ctx); + return 0; + } + + return -1; +} + static int gdb_handle_packet(GDBState *s, const char *line_buf) { CPUState *cpu; --=20 2.20.1