From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mail-wr1-x430.google.com (mail-wr1-x430.google.com [IPv6:2a00:1450:4864:20::430]) by sourceware.org (Postfix) with ESMTPS id E81533857C53 for ; Wed, 13 Oct 2021 21:59:19 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.1 sourceware.org E81533857C53 Authentication-Results: sourceware.org; dmarc=none (p=none dis=none) header.from=embecosm.com Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=embecosm.com Received: by mail-wr1-x430.google.com with SMTP id u18so13063087wrg.5 for ; Wed, 13 Oct 2021 14:59:19 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=embecosm.com; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=ZBkAaXaPZPH6NM+2ZS/3z0jkHMnVgrwE32vhAGT6sAo=; b=SnKLSsckarAHkgraIv6xSUyZ558ZfIttMsGCkEYWxHqecOJNGvGc074SdEL9hg7UuQ zWp5hFBQTeGdg37BPrrY2+/qvRI9iDNZSPITGeDFBVihkJtyOfXIVpN28fy8wToBd07e b0UhGm8NBqY0eMy36j4HkrbMv83cD25hLtQMu+pgnGJ55nB1d1DVtK+fmhoL0Q2yEhqf JfHTpDqD1ofCKZtO5cZWhWl1AUOscQI07DezyyeXFgZtZHyNST5C/rZuIXNigOl6VwNP z8ISJAg7wgfzYJJsJCgywncMSychBGtgIYZlIqQ0O9qyMZDZS5FAX3ovprhpqOyIrILb kXrA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=ZBkAaXaPZPH6NM+2ZS/3z0jkHMnVgrwE32vhAGT6sAo=; b=N7RBe5U94aKqag5CcYMTeo77vAdf8fBRRf446F5QQQ2leYaQZ7OwSY3j3u6/xcPlm1 6bPHGNKyemy0oqoGWZJyM0+L5Lbcdcoe+QMZ0WgQBSNTeMkJU8Kbd59g3uPRwOwF6gw1 lQsUN7Sk3ll/6+tMpNRKeIM2xrzzT+ZBn7CjdYPbPgoyCz703uUirg8i4yRrfHQKsJry Cmx0DwktQb4rLutx6lWQEaM3WQW6+45dymNSkY7UC3x54ZbXDPLz+hBAz3auwBCYRCw2 tsmAiX+aHy/BVCJ6Y7Vvue8+5wp0jF//hCUirF1UqFjyAFc1YsxoOWNjdSfJqvYjqgGG JUlA== X-Gm-Message-State: AOAM531MTuIBJlPlGbw+LlOsr40sUJlNUk3yR8Q8YvSDO790iZEc07kg MY+C2ql1Y8CKMcrCf2fB/z1OM7zAShCAWg== X-Google-Smtp-Source: ABdhPJwQZZLp/WKioOY/2IJJmua3xzfY1CWcE6gVF/mNzD5pIVYaKDMxA7NoI22VNbv5Zuj79l4YZg== X-Received: by 2002:a1c:4645:: with SMTP id t66mr1823561wma.179.1634162358304; Wed, 13 Oct 2021 14:59:18 -0700 (PDT) Received: from localhost (host212-140-123-151.range212-140.btcentralplus.com. [212.140.123.151]) by smtp.gmail.com with ESMTPSA id a5sm682746wrn.71.2021.10.13.14.59.17 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 13 Oct 2021 14:59:18 -0700 (PDT) From: Andrew Burgess To: gdb-patches@sourceware.org Subject: [PATCH 4/5] gdb: add extension language print_insn hook Date: Wed, 13 Oct 2021 22:59:09 +0100 Message-Id: <150de80644ec955df5850ef74f6274ccc032a6f8.1634162144.git.andrew.burgess@embecosm.com> X-Mailer: git-send-email 2.25.4 In-Reply-To: References: MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Spam-Status: No, score=-11.8 required=5.0 tests=BAYES_00, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, GIT_PATCH_0, RCVD_IN_DNSWL_NONE, SPF_HELO_NONE, SPF_PASS, TXREP autolearn=ham autolearn_force=no version=3.4.4 X-Spam-Checker-Version: SpamAssassin 3.4.4 (2020-01-24) on server2.sourceware.org X-BeenThere: gdb-patches@sourceware.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Gdb-patches mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Wed, 13 Oct 2021 21:59:21 -0000 This commit is setup for the next commit. In the next commit I plan to add a Python API to intercept the print_insn calls within GDB, each print_insn call is responsible for disassembling, and print one instruction. After the next commit it will be possible for a user to write Python code that either wraps around the existing disassembler, or even, in extreme situations, entirely replaces the existing disassembler. This commit does not add any new Python API. What this commit does is put the extension language framework in place for a print_insn hook. There's a new callback added to 'struct extension_language_ops', which is then filled in with NULL for Python and Guile. Finally, in the disassembler, the code is restructured so that the new extension language function ext_lang_print_insn is called before we delegate to gdbarch_print_insn. After this, the next commit can focus entirely on providing a Python implementation of the new print_insn callback. There should be no user visible change after this commit. --- gdb/disasm.c | 27 +++++++++++++++++++++++++-- gdb/extension-priv.h | 15 +++++++++++++++ gdb/extension.c | 20 ++++++++++++++++++++ gdb/extension.h | 17 +++++++++++++++++ gdb/guile/guile.c | 6 +++++- gdb/python/python.c | 2 ++ 6 files changed, 84 insertions(+), 3 deletions(-) diff --git a/gdb/disasm.c b/gdb/disasm.c index c045dfc94a6..0c384c778f5 100644 --- a/gdb/disasm.c +++ b/gdb/disasm.c @@ -784,13 +784,36 @@ gdb_disassembler::~gdb_disassembler () disassemble_free_target (&m_di); } +/* Wrapper around calling gdbarch_print_insn. This function takes care of + first calling the extension language hooks for print_insn, and, if none + of the extension languages can print this instruction, calls + gdbarch_print_insn to do the work. + + GDBARCH is the architecture to disassemble in, VMA is the address of the + instruction being disassembled, and INFO is the libopcodes disassembler + related information. */ + +static int +gdb_print_insn_1 (struct gdbarch *gdbarch, CORE_ADDR vma, + struct disassemble_info *info) +{ + /* Call into the extension languages to do the disassembly. */ + gdb::optional length = ext_lang_print_insn (gdbarch, vma, info); + if (length.has_value ()) + return *length; + + /* No extension language wanted to do the disassembly, so do it + manually. */ + return gdbarch_print_insn (gdbarch, vma, info); +} + int gdb_disassembler::print_insn (CORE_ADDR memaddr, int *branch_delay_insns) { m_err_memaddr.reset (); - int length = gdbarch_print_insn (arch (), memaddr, &m_di); + int length = gdb_print_insn_1 (arch (), memaddr, &m_di); if (length < 0) { @@ -916,7 +939,7 @@ gdb_buffered_insn_length (struct gdbarch *gdbarch, gdb_buffered_insn_length_init_dis (gdbarch, &di, insn, max_len, addr, &disassembler_options_holder); - int result = gdbarch_print_insn (gdbarch, addr, &di); + int result = gdb_print_insn_1 (gdbarch, addr, &di); disassemble_free_target (&di); return result; } diff --git a/gdb/extension-priv.h b/gdb/extension-priv.h index 77f23e0f911..6c5cde12ffd 100644 --- a/gdb/extension-priv.h +++ b/gdb/extension-priv.h @@ -257,6 +257,21 @@ struct extension_language_ops or an empty option. */ gdb::optional (*colorize) (const std::string &name, const std::string &contents); + + /* Print a single instruction from ADDRESS in architecture GDBARCH. INFO + is the standard libopcodes disassembler_info structure. Bytes for the + instruction being printed should be read using INFO->read_memory_func + as the actual instruction bytes might be in a buffer. + + Use INFO->fprintf_func to print the results of the disassembly, and + return the length of the instruction. + + If no instruction can be disassembled then return an empty value and + other extension languages will get a chance to perform the + disassembly. */ + gdb::optional (*print_insn) (struct gdbarch *gdbarch, + CORE_ADDR address, + struct disassemble_info *info); }; /* State necessary to restore a signal handler to its previous value. */ diff --git a/gdb/extension.c b/gdb/extension.c index 27dce9befa0..9a002e425b1 100644 --- a/gdb/extension.c +++ b/gdb/extension.c @@ -893,6 +893,26 @@ ext_lang_colorize (const std::string &filename, const std::string &contents) return result; } +/* See extension.h. */ + +gdb::optional +ext_lang_print_insn (struct gdbarch *gdbarch, CORE_ADDR address, + struct disassemble_info *info) +{ + for (const struct extension_language_defn *extlang : extension_languages) + { + if (extlang->ops == nullptr + || extlang->ops->print_insn == nullptr) + continue; + gdb::optional length + (extlang->ops->print_insn (gdbarch, address, info)); + if (length.has_value ()) + return length; + } + + return {}; +} + /* Called via an observer before gdb prints its prompt. Iterate over the extension languages giving them a chance to change the prompt. The first one to change the prompt wins, diff --git a/gdb/extension.h b/gdb/extension.h index 56f57560de3..fa292a6cb4f 100644 --- a/gdb/extension.h +++ b/gdb/extension.h @@ -319,4 +319,21 @@ extern void get_matching_xmethod_workers extern gdb::optional ext_lang_colorize (const std::string &filename, const std::string &contents); +/* Try to disassemble a single instruction. ADDRESS is the address that + the instructions apparent address, though bytes for the instruction + should be read by calling INFO->read_memory_func as we might be + disassembling out of a buffer. GDBARCH is the architecture in which we + are performing the disassembly. + + The disassembled instruction should be printed by calling + INFO->fprintf_func, and the length (in octets) of the disassembled + instruction should be returned. + + If no instruction could be disassembled then an empty value is returned + and GDB will call gdbarch_print_insn to perform the disassembly + itself. */ + +extern gdb::optional ext_lang_print_insn + (struct gdbarch *gdbarch, CORE_ADDR address, struct disassemble_info *info); + #endif /* EXTENSION_H */ diff --git a/gdb/guile/guile.c b/gdb/guile/guile.c index 8ba840cba6a..92f2f5c78ef 100644 --- a/gdb/guile/guile.c +++ b/gdb/guile/guile.c @@ -130,8 +130,12 @@ static const struct extension_language_ops guile_extension_ops = gdbscm_breakpoint_has_cond, gdbscm_breakpoint_cond_says_stop, - NULL, /* gdbscm_check_quit_flag, */ NULL, /* gdbscm_set_quit_flag, */ + NULL, /* gdbscm_check_quit_flag, */ + NULL, /* gdbscm_before_prompt, */ + NULL, /* gdbscm_get_matching_xmethod_workers */ + NULL, /* gdbscm_colorize */ + NULL, /* gdbscm_print_insn */ }; #endif diff --git a/gdb/python/python.c b/gdb/python/python.c index 2c2d8c5f217..d817bd5bf27 100644 --- a/gdb/python/python.c +++ b/gdb/python/python.c @@ -189,6 +189,8 @@ const struct extension_language_ops python_extension_ops = gdbpy_get_matching_xmethod_workers, gdbpy_colorize, + + NULL, /* gdbpy_print_insn, */ }; /* Architecture and language to be used in callbacks from -- 2.25.4