diff --git a/gdb/gdb_bfd.c b/gdb/gdb_bfd.c index 6d7b7fa84e5..cb9a91d0923 100644 --- a/gdb/gdb_bfd.c +++ b/gdb/gdb_bfd.c @@ -930,6 +930,29 @@ gdb_bfd_openw (const char *filename, const char *target) return gdb_bfd_ref_ptr::new_reference (result); } +/* Wrap f (args) and handle exceptions by: + - returning val, and + - calling set_quit_flag or set_force_quit_flag, if needed. */ + +template +static R +catch_exceptions (F &&f, Args&&... args) +{ + try + { + return f (std::forward (args)...); + } + catch (const gdb_exception &ex) + { + if (ex.reason == RETURN_QUIT) + set_quit_flag (); + else if (ex.reason == RETURN_FORCED_QUIT) + set_force_quit_flag (); + } + + return val; +} + /* See gdb_bfd.h. */ gdb_bfd_ref_ptr @@ -939,21 +962,51 @@ gdb_bfd_openr_iovec (const char *filename, const char *target, auto do_open = [] (bfd *nbfd, void *closure) -> void * { auto real_opener = static_cast (closure); - return (*real_opener) (nbfd); + /* Prevent exceptions from escaping to C code and triggering an abort. */ + auto res = catch_exceptions ([&] + { + return (*real_opener) (nbfd); + }); + if (res == nullptr) + { + errno = EIO; + bfd_set_error (bfd_error_system_call); + } + return res; }; auto read_trampoline = [] (bfd *nbfd, void *stream, void *buf, file_ptr nbytes, file_ptr offset) -> file_ptr { gdb_bfd_iovec_base *obj = static_cast (stream); - return obj->read (nbfd, buf, nbytes, offset); + /* Prevent exceptions from escaping to C code and triggering an abort. */ + auto res = catch_exceptions ([&] + { + return obj->read (nbfd, buf, nbytes, offset); + }); + if (res == -1) + { + errno = EIO; + bfd_set_error (bfd_error_system_call); + } + return res; }; auto stat_trampoline = [] (struct bfd *abfd, void *stream, struct stat *sb) -> int { gdb_bfd_iovec_base *obj = static_cast (stream); - return obj->stat (abfd, sb); + /* Prevent exceptions from escaping to C code and triggering an abort. */ + auto res = catch_exceptions ([&] + { + return obj->stat (abfd, sb); + }); + if (res == -1) + { + errno = EIO; + bfd_set_error (bfd_error_system_call); + } + return res; }; auto close_trampoline = [] (struct bfd *nbfd, void *stream) -> int