gdb/disasm: mark functions passed to the disassembler noexcept

While working on another patch, Simon pointed out that GDB could be
improved by marking the functions passed to the disassembler as
noexcept.

  https://sourceware.org/pipermail/gdb-patches/2022-October/193084.html

The reason this is important is the on some hosts, libopcodes, being C
code, will not be compiled with support for handling exceptions.  As
such, an attempt to throw an exception over libopcodes code will cause
GDB to terminate.

See bug gdb/29712 for an example of when this happened.

In this commit all the functions that are passed to the disassembler,
and which might be used as callbacks by libopcodes are marked
noexcept.

Ideally, I would have liked to change these typedefs:

  using read_memory_ftype = decltype (disassemble_info::read_memory_func);
  using memory_error_ftype = decltype (disassemble_info::memory_error_func);
  using print_address_ftype = decltype (disassemble_info::print_address_func);
  using fprintf_ftype = decltype (disassemble_info::fprintf_func);
  using fprintf_styled_ftype = decltype (disassemble_info::fprintf_styled_func);

which are declared in disasm.h, as including the noexcept keyword.
However, when I tried this, I ran into this warning/error:

  In file included from ../../src/gdb/disasm.c:25:
  ../../src/gdb/disasm.h: In constructor ‘gdb_printing_disassembler::gdb_printing_disassembler(gdbarch*, ui_file*, gdb_disassemble_info::read_memory_ftype, gdb_disassemble_info::memory_error_ftype, gdb_disassemble_info::print_address_ftype)’:
  ../../src/gdb/disasm.h:116:3: error: mangled name for ‘gdb_printing_disassembler::gdb_printing_disassembler(gdbarch*, ui_file*, gdb_disassemble_info::read_memory_ftype, gdb_disassemble_info::memory_error_ftype, gdb_disassemble_info::print_address_ftype)’ will change in C++17 because the exception specification is part of a function type [-Werror=noexcept-type]
    116 |   gdb_printing_disassembler (struct gdbarch *gdbarch,
        |   ^~~~~~~~~~~~~~~~~~~~~~~~~

So I've left that change out.  This does mean that if somebody adds a
new use of the disassembler classes in the future, and forgets to mark
the callbacks as noexcept, this will compile fine.  We'll just have to
manually check for that during review.
This commit is contained in:
Andrew Burgess 2022-10-24 18:35:41 +01:00
parent 65639fcc54
commit 8eb7d135e3
5 changed files with 37 additions and 29 deletions

View file

@ -234,7 +234,8 @@ print_one_insn_test (struct gdbarch *gdbarch)
size_t m_len; size_t m_len;
static int read_memory (bfd_vma memaddr, gdb_byte *myaddr, static int read_memory (bfd_vma memaddr, gdb_byte *myaddr,
unsigned int len, struct disassemble_info *info) unsigned int len,
struct disassemble_info *info) noexcept
{ {
gdb_disassembler_test *self gdb_disassembler_test *self
= static_cast<gdb_disassembler_test *>(info->application_data); = static_cast<gdb_disassembler_test *>(info->application_data);
@ -296,7 +297,7 @@ memory_error_test (struct gdbarch *gdbarch)
static int read_memory (bfd_vma memaddr, gdb_byte *myaddr, static int read_memory (bfd_vma memaddr, gdb_byte *myaddr,
unsigned int len, unsigned int len,
struct disassemble_info *info) struct disassemble_info *info) noexcept
{ {
/* Always return an error. */ /* Always return an error. */
return -1; return -1;

View file

@ -191,7 +191,7 @@ line_has_code_p (htab_t table, struct symtab *symtab, int line)
int int
gdb_disassembler_memory_reader::dis_asm_read_memory gdb_disassembler_memory_reader::dis_asm_read_memory
(bfd_vma memaddr, gdb_byte *myaddr, unsigned int len, (bfd_vma memaddr, gdb_byte *myaddr, unsigned int len,
struct disassemble_info *info) struct disassemble_info *info) noexcept
{ {
return target_read_code (memaddr, myaddr, len); return target_read_code (memaddr, myaddr, len);
} }
@ -199,8 +199,8 @@ gdb_disassembler_memory_reader::dis_asm_read_memory
/* Wrapper of memory_error. */ /* Wrapper of memory_error. */
void void
gdb_disassembler::dis_asm_memory_error (int err, bfd_vma memaddr, gdb_disassembler::dis_asm_memory_error
struct disassemble_info *info) (int err, bfd_vma memaddr, struct disassemble_info *info) noexcept
{ {
gdb_disassembler *self gdb_disassembler *self
= static_cast<gdb_disassembler *>(info->application_data); = static_cast<gdb_disassembler *>(info->application_data);
@ -211,8 +211,8 @@ gdb_disassembler::dis_asm_memory_error (int err, bfd_vma memaddr,
/* Wrapper of print_address. */ /* Wrapper of print_address. */
void void
gdb_disassembler::dis_asm_print_address (bfd_vma addr, gdb_disassembler::dis_asm_print_address
struct disassemble_info *info) (bfd_vma addr, struct disassemble_info *info) noexcept
{ {
gdb_disassembler *self gdb_disassembler *self
= static_cast<gdb_disassembler *>(info->application_data); = static_cast<gdb_disassembler *>(info->application_data);
@ -256,7 +256,7 @@ gdb_printing_disassembler::stream_from_gdb_disassemble_info (void *dis_info)
int int
gdb_printing_disassembler::fprintf_func (void *dis_info, gdb_printing_disassembler::fprintf_func (void *dis_info,
const char *format, ...) const char *format, ...) noexcept
{ {
ui_file *stream = stream_from_gdb_disassemble_info (dis_info); ui_file *stream = stream_from_gdb_disassemble_info (dis_info);
@ -272,9 +272,9 @@ gdb_printing_disassembler::fprintf_func (void *dis_info,
/* See disasm.h. */ /* See disasm.h. */
int int
gdb_printing_disassembler::fprintf_styled_func (void *dis_info, gdb_printing_disassembler::fprintf_styled_func
enum disassembler_style style, (void *dis_info, enum disassembler_style style,
const char *format, ...) const char *format, ...) noexcept
{ {
ui_file *stream = stream_from_gdb_disassemble_info (dis_info); ui_file *stream = stream_from_gdb_disassemble_info (dis_info);
gdb_printing_disassembler *dis = (gdb_printing_disassembler *) dis_info; gdb_printing_disassembler *dis = (gdb_printing_disassembler *) dis_info;
@ -1220,8 +1220,8 @@ gdb_insn_length (struct gdbarch *gdbarch, CORE_ADDR addr)
/* See disasm.h. */ /* See disasm.h. */
int int
gdb_non_printing_disassembler::null_fprintf_func (void *stream, gdb_non_printing_disassembler::null_fprintf_func
const char *format, ...) (void *stream, const char *format, ...) noexcept
{ {
return 0; return 0;
} }
@ -1230,7 +1230,8 @@ gdb_non_printing_disassembler::null_fprintf_func (void *stream,
int int
gdb_non_printing_disassembler::null_fprintf_styled_func gdb_non_printing_disassembler::null_fprintf_styled_func
(void *stream, enum disassembler_style style, const char *format, ...) (void *stream, enum disassembler_style style,
const char *format, ...) noexcept
{ {
return 0; return 0;
} }

View file

@ -51,7 +51,13 @@ struct gdb_disassemble_info
protected: protected:
/* Types for the function callbacks within m_di. */ /* Types for the function callbacks within m_di. It would be nice if
these function types were all defined to include the noexcept
keyword, as every implementation of these must be noexcept. However,
using noexcept within a function typedef like this is a C++17
feature, trying to do this for earlier C++ versions results in a
warning from GCC/Clang, and the noexcept isn't checked. After we
move to C++17 these should be updated to add noexcept. */
using read_memory_ftype = decltype (disassemble_info::read_memory_func); using read_memory_ftype = decltype (disassemble_info::read_memory_func);
using memory_error_ftype = decltype (disassemble_info::memory_error_func); using memory_error_ftype = decltype (disassemble_info::memory_error_func);
using print_address_ftype = decltype (disassemble_info::print_address_func); using print_address_ftype = decltype (disassemble_info::print_address_func);
@ -127,7 +133,7 @@ protected:
/* Callback used as the disassemble_info's fprintf_func callback. The /* Callback used as the disassemble_info's fprintf_func callback. The
DIS_INFO pointer is a pointer to a gdb_printing_disassembler object. DIS_INFO pointer is a pointer to a gdb_printing_disassembler object.
Content is written to the m_stream extracted from DIS_INFO. */ Content is written to the m_stream extracted from DIS_INFO. */
static int fprintf_func (void *dis_info, const char *format, ...) static int fprintf_func (void *dis_info, const char *format, ...) noexcept
ATTRIBUTE_PRINTF(2,3); ATTRIBUTE_PRINTF(2,3);
/* Callback used as the disassemble_info's fprintf_styled_func callback. /* Callback used as the disassemble_info's fprintf_styled_func callback.
@ -135,7 +141,7 @@ protected:
object. Content is written to the m_stream extracted from DIS_INFO. */ object. Content is written to the m_stream extracted from DIS_INFO. */
static int fprintf_styled_func (void *dis_info, static int fprintf_styled_func (void *dis_info,
enum disassembler_style style, enum disassembler_style style,
const char *format, ...) const char *format, ...) noexcept
ATTRIBUTE_PRINTF(3,4); ATTRIBUTE_PRINTF(3,4);
/* Return true if the disassembler is considered inside a comment, false /* Return true if the disassembler is considered inside a comment, false
@ -187,14 +193,14 @@ private:
/* Callback used as the disassemble_info's fprintf_func callback, this /* Callback used as the disassemble_info's fprintf_func callback, this
doesn't write anything to STREAM, but just returns 0. */ doesn't write anything to STREAM, but just returns 0. */
static int null_fprintf_func (void *stream, const char *format, ...) static int null_fprintf_func (void *stream, const char *format, ...) noexcept
ATTRIBUTE_PRINTF(2,3); ATTRIBUTE_PRINTF(2,3);
/* Callback used as the disassemble_info's fprintf_styled_func callback, /* Callback used as the disassemble_info's fprintf_styled_func callback,
, this doesn't write anything to STREAM, but just returns 0. */ , this doesn't write anything to STREAM, but just returns 0. */
static int null_fprintf_styled_func (void *stream, static int null_fprintf_styled_func (void *stream,
enum disassembler_style style, enum disassembler_style style,
const char *format, ...) const char *format, ...) noexcept
ATTRIBUTE_PRINTF(3,4); ATTRIBUTE_PRINTF(3,4);
}; };
@ -208,7 +214,7 @@ struct gdb_disassembler_memory_reader
/* Implements the read_memory_func disassemble_info callback. */ /* Implements the read_memory_func disassemble_info callback. */
static int dis_asm_read_memory (bfd_vma memaddr, gdb_byte *myaddr, static int dis_asm_read_memory (bfd_vma memaddr, gdb_byte *myaddr,
unsigned int len, unsigned int len,
struct disassemble_info *info); struct disassemble_info *info) noexcept;
}; };
/* A non-printing disassemble_info management class. The disassemble_info /* A non-printing disassemble_info management class. The disassemble_info
@ -281,9 +287,9 @@ private:
static bool use_ext_lang_colorization_p; static bool use_ext_lang_colorization_p;
static void dis_asm_memory_error (int err, bfd_vma memaddr, static void dis_asm_memory_error (int err, bfd_vma memaddr,
struct disassemble_info *info); struct disassemble_info *info) noexcept;
static void dis_asm_print_address (bfd_vma addr, static void dis_asm_print_address (bfd_vma addr,
struct disassemble_info *info); struct disassemble_info *info) noexcept;
/* Return true if we should use the extension language to apply /* Return true if we should use the extension language to apply
disassembler styling. This requires disassembler styling to be on disassembler styling. This requires disassembler styling to be on

View file

@ -106,7 +106,7 @@ gdbscm_disasm_read_memory_worker (void *datap)
static int static int
gdbscm_disasm_read_memory (bfd_vma memaddr, bfd_byte *myaddr, gdbscm_disasm_read_memory (bfd_vma memaddr, bfd_byte *myaddr,
unsigned int length, unsigned int length,
struct disassemble_info *dinfo) struct disassemble_info *dinfo) noexcept
{ {
gdbscm_disassembler *self gdbscm_disassembler *self
= static_cast<gdbscm_disassembler *> (dinfo->application_data); = static_cast<gdbscm_disassembler *> (dinfo->application_data);

View file

@ -101,12 +101,12 @@ struct gdbpy_disassembler : public gdb_printing_disassembler
/* Callbacks used by disassemble_info. */ /* Callbacks used by disassemble_info. */
static void memory_error_func (int status, bfd_vma memaddr, static void memory_error_func (int status, bfd_vma memaddr,
struct disassemble_info *info); struct disassemble_info *info) noexcept;
static void print_address_func (bfd_vma addr, static void print_address_func (bfd_vma addr,
struct disassemble_info *info); struct disassemble_info *info) noexcept;
static int read_memory_func (bfd_vma memaddr, gdb_byte *buff, static int read_memory_func (bfd_vma memaddr, gdb_byte *buff,
unsigned int len, unsigned int len,
struct disassemble_info *info); struct disassemble_info *info) noexcept;
/* Return a reference to an optional that contains the address at which a /* Return a reference to an optional that contains the address at which a
memory error occurred. The optional will only have a value if a memory error occurred. The optional will only have a value if a
@ -513,7 +513,7 @@ disasmpy_info_progspace (PyObject *self, void *closure)
int int
gdbpy_disassembler::read_memory_func (bfd_vma memaddr, gdb_byte *buff, gdbpy_disassembler::read_memory_func (bfd_vma memaddr, gdb_byte *buff,
unsigned int len, unsigned int len,
struct disassemble_info *info) struct disassemble_info *info) noexcept
{ {
gdbpy_disassembler *dis gdbpy_disassembler *dis
= static_cast<gdbpy_disassembler *> (info->application_data); = static_cast<gdbpy_disassembler *> (info->application_data);
@ -658,7 +658,7 @@ disasmpy_result_init (PyObject *self, PyObject *args, PyObject *kwargs)
void void
gdbpy_disassembler::memory_error_func (int status, bfd_vma memaddr, gdbpy_disassembler::memory_error_func (int status, bfd_vma memaddr,
struct disassemble_info *info) struct disassemble_info *info) noexcept
{ {
gdbpy_disassembler *dis gdbpy_disassembler *dis
= static_cast<gdbpy_disassembler *> (info->application_data); = static_cast<gdbpy_disassembler *> (info->application_data);
@ -669,7 +669,7 @@ gdbpy_disassembler::memory_error_func (int status, bfd_vma memaddr,
void void
gdbpy_disassembler::print_address_func (bfd_vma addr, gdbpy_disassembler::print_address_func (bfd_vma addr,
struct disassemble_info *info) struct disassemble_info *info) noexcept
{ {
gdbpy_disassembler *dis gdbpy_disassembler *dis
= static_cast<gdbpy_disassembler *> (info->application_data); = static_cast<gdbpy_disassembler *> (info->application_data);